Search code examples
pythonqt4pyqt4qtablewidgetqtablewidgetitem

How do I get some slot/function to be executed when a certain QTableWidgetItem is checked / unchecked in PyQt


I have a dynamically created table, that has N rows and M QTableWidgetItems (that are only used as checkboxes) per row - I need to run code that knows the row and the column whenever a checkbox is checked or unchecked.

My CheckBox subclass looks like:

class CheckBox(QTableWidgetItem):
    def __init__(self):
        QTableWidgetItem.__init__(self,1000)
        self.setTextAlignment(Qt.AlignVCenter | Qt.AlignJustify)
        self.setFlags(Qt.ItemFlags(
            Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled ))
def stateChanged(self):
    do_something(self.row(),self.column())
    ...

Obviously this does not redefine the function that gets called when SIGNAL('stateChanged(int)') -thingy happens, because, well, nothing happens.

But, if I do:

item = CheckBox()
self.connect(item, SIGNAL('stateChanged(int)'), item.stateChanged)

In the loop creating the table, I get an error:

TypeError: arguments did not match any overloaded call:
  QObject.connect(QObject, SIGNAL(), QObject, SLOT(), Qt.ConnectionType=Qt.AutoConnection): argument 1 has unexpected type 'CheckBox'
  QObject.connect(QObject, SIGNAL(), callable, Qt.ConnectionType=Qt.AutoConnection): argument 1 has unexpected type 'CheckBox'
  QObject.connect(QObject, SIGNAL(), SLOT(), Qt.ConnectionType=Qt.AutoConnection): argument 1 has unexpected type 'CheckBox

EDIT: I also tried redefining setCheckState() but apparently that does NOT get called when the item is checked or unchecked.

EDIT 2: Furthermore, changing the connect to

self.connect(self.table, SIGNAL('itemClicked(item)'),
               self.table.stateChanged)

where table = QTableWidget() does not help either.

How do I do this the right way?


Solution

  • The simplest solution is probably connecting to the cellChanged(int, int) signal of the QTableWidget; take a look at the following example:

    import sys
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    
    #signal handler
    def myCellChanged(row, col):
        print row, col
    
    #just a helper function to setup the table
    def createCheckItem(table, row, col):
        check = QTableWidgetItem("Test")
        check.setCheckState(Qt.Checked)
        table.setItem(row,col,check)
    
    app = QApplication(sys.argv)
    
    #create the 5x5 table...
    table = QTableWidget(5,5)
    map(lambda (row,col): createCheckItem(table, row, col),
       [(row, col) for row in range(0, 5) for col in range(0, 5)])
    table.show()
    
    #...and connect our signal handler to the cellChanged(int, int) signal
    QObject.connect(table, SIGNAL("cellChanged(int, int)"), myCellChanged)
    app.exec_()
    

    It creates a 5x5 table of checkboxes; whenever one of them is checked/unchecked, myCellChanged is called and prints the row and column of the changed checkbox; you can then of course use QTableWidget.item(someRow, someColumn).checkState() to see whether it was checked or unchecked.