Search code examples
pythonpyqtpyqt4qabstracttablemodelqcheckbox

PyQt QAbstractTableModel checkbox not checkable


I am using own table model with QAbstractTableModel, where I have first col with checkbox (checkable cause flags Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled). I have trouble when I am trying use checkboxes, cause they are not checkable (can not make check or uncheck in them) in showed table.

What am I doing wrong? I am using this methods in own table model class:

def data(self, index, role):

    row = index.row()
    col = index.column()

    if role == Qt.DisplayRole:
        return '{0}'.format(self.tableData[row][col])

    if role == Qt.CheckStateRole: 
        if col == 0:
            return Qt.Unchecked
        else: 
            return None

def setData(self, index, value, role):
    if not index.isValid():
       return False

    if (role == Qt.CheckStateRole):
        if (index.data(Qt.CheckStateRole) == Qt.Checked):
            return True
        else:
            return False
    else:
        return False

Solution

  • You have to store the states for it, we need to have something permanent as a reference, for this we use QPersistentModelIndex, in this case a dictionary where the key is the QPersistentModelIndex and the value is the state of QCheckBox.

    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    
    
    class TableModel(QAbstractTableModel):
        def __init__(self, parent=None):
            super(TableModel, self).__init__(parent)
            self.tableData = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
            self.checks = {}
    
        def columnCount(self, *args):
            return 3
    
        def rowCount(self, *args):
            return 3
    
        def checkState(self, index):
            if index in self.checks.keys():
                return self.checks[index]
            else:
                return Qt.Unchecked
    
        def data(self, index, role=Qt.DisplayRole):
            row = index.row()
            col = index.column()
            if role == Qt.DisplayRole:
                return '{0}'.format(self.tableData[row][col])
            elif role == Qt.CheckStateRole and col == 0:
                return self.checkState(QPersistentModelIndex(index))
            return None
    
        def setData(self, index, value, role=Qt.EditRole):
    
            if not index.isValid():
                return False
            if role == Qt.CheckStateRole:
                self.checks[QPersistentModelIndex(index)] = value
                return True
            return False
    
        def flags(self, index):
            fl = QAbstractTableModel.flags(self, index)
            if index.column() == 0:
                fl |= Qt.ItemIsEditable | Qt.ItemIsUserCheckable
            return fl
    
    
    if __name__ == "__main__":
        import sys
    
        app = QApplication(sys.argv)
        view = QTableView()
        model = TableModel()
        view.setModel(model)
        view.show()
        sys.exit(app.exec_())