Search code examples
pythonpyqtpyqt4

how to get the subtotal amount i.e according to user given in quantity spinbox of qtable widget in pyqt4?


According to the following table and the code which I constructed as an example, I require a proper code & table from which we can obtain the values of the 'Quantity' & 'Rate'(price) to be displayed as 'Subtotal' (Subtotal = Quantity * Rate). Its little bit confusing to understand the exact logic here.

here my code is given bellow:

enter image description here

from PyQt4 import QtGui, QtCore

import sys


class Example(QtGui.QWidget):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):
      self. table = QtGui.QTableWidget(self)
      self.table.move(10,70)
      self.table.resize(500,300)
      self.table_item = QtGui.QTableWidgetItem()
      self.table.setRowCount(3)
      self.table.verticalHeader().hide()
      self.table.setColumnCount(6)
      self.table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)

      self.fnt = self.table.font()
      self.fnt.setPointSize(11)
      self.table.setFont(self.fnt)

      self.table.setHorizontalHeaderLabels(("S.no, Item Description,Qty,Rate(Rs:),Subtotal,"",").split(','))
      self.table.setItem(0,0,QtGui.QTableWidgetItem("1"))
      self.table.setItem(0,1, QtGui.QTableWidgetItem("Acne-aid Wash Facial Cleansing"))
      self.table.setItem(0,3,QtGui.QTableWidgetItem("191.72"))
      self.table.setItem(0,5,QtGui.QTableWidgetItem(""))


      self.table.setItem(1,1,QtGui.QTableWidgetItem("Moisturizer"))
      self.table.setItem(1,3,QtGui.QTableWidgetItem("90"))
      self.table.setItem(1,5,QtGui.QTableWidgetItem(""))
      self.table.setItem(1,0,QtGui.QTableWidgetItem("2"))


      self.table.setItem(2,0,QtGui.QTableWidgetItem("3"))
      self.table.setItem(2,1,QtGui.QTableWidgetItem("Brightening eye cream"))
      self.table.setItem(2,3,QtGui.QTableWidgetItem("40"))
      self.table.setItem(2,5,QtGui.QTableWidgetItem(""))
      for x in range(0,4):
         self.spin = QtGui.QSpinBox()
         self.spin.setMinimum(1)
         self.spin.setMaximum(50)
         self.table.setCellWidget(x,2,self.spin)
      for x in range(0,4):
           self.btn = QtGui.QPushButton(self)
           self.btn.setIcon(QtGui.QIcon("trash1.png"))
           self.table.setCellWidget(x,5,self.btn)

           self.setWindowTitle("To do app")
           self.setGeometry(200,300,600,300)
           self.show()
def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_()) 


if __name__ == '__main__':
    main()

Solution

  • The solution is to connect the valueChanged signal of the QSpinBox to any slot where the calculated is done, that signal sends the information of the current value but does not indicate the row to which the QSpinBox belongs. For this we use functool.partial to indicate the row (another option is to use a lambda function).

    On the other hand I have improved your code, I see that you abuse self, for example in a for-loop the variables that are created inside must not be created using self. Also I have reduced the code with which you create the data.

    import sys
    from functools import partial
    from PyQt4 import QtGui, QtCore
    
    
    class Example(QtGui.QWidget):
        def __init__(self):
            super(Example, self).__init__()
            self.initUI()
    
        def initUI(self):
            self. table = QtGui.QTableWidget(3, 6, self)
            self.table.setGeometry(10, 70, 500,300)
    
            self.table.verticalHeader().hide()
            self.table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
    
            fnt = self.table.font()
            fnt.setPointSize(11)
            self.table.setFont(fnt)
    
            self.table.setHorizontalHeaderLabels(("S.no, Item Description,Qty,Rate(Rs:),Subtotal,"",").split(','))
    
            all_data = [("1", "Acne-aid Wash Facial Cleansing", 191.72, 0),
                        ("2", "AMoisturizer", 90, 0),
                        ("3", "Brightening eye cream", 40, 0)]
    
            for r, row_data in enumerate(all_data):
                for c, value in zip((0, 1, 3, 4), row_data):
                    it = QtGui.QTableWidgetItem(str(value))
                    self.table.setItem(r, c, it)
    
            for r in range(self.table.rowCount()):
    
                spin = QtGui.QSpinBox(minimum=0, maximum=50)
                spin.valueChanged.connect(partial(self.calculateSubTotal, r))
                self.table.setCellWidget(r, 2, spin)
    
                btn = QtGui.QPushButton(icon=QtGui.QIcon("trash1.png"))
                self.table.setCellWidget(r, 5, btn)
    
            self.setWindowTitle("To do app")
            self.setGeometry(200, 300, 600, 300)
            self.show()
    
    
        def calculateSubTotal(self, row, value):
            rate = float(self.table.item(row, 3).text())
            subtotal = value * rate
    
            item_subtotal = self.table.item(row, 4)
            if item_subtotal is None:
                item_subtotal = QtGui.QTableWidgetItem()
                self.table.setItem(row, 4, item_subtotal)
    
            item_subtotal.setText(str(subtotal))
    
    def main():
        app = QtGui.QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_()) 
    
    
    if __name__ == '__main__':
        main()