Search code examples
pythonpyqt5qtablewidget

Toggle the editability of a QTableWidget in Python


I would like to be able to make a table with cells which were previously un-editable to be editable. And then control/toggle the editability of the table by attaching the function to a button.

from PyQt5 import QtCore, QtWidgets


class ReadOnlyDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        # last column
        #if index.column() == (index.model().columnCount() - 1):
        return super().createEditor(parent, option, index)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        table_widget = QtWidgets.QTableWidget(4, 3)
        self.setCentralWidget(table_widget)
        
        
        item = QTableWidgetItem(str('wait'))
        item_2 = QTableWidgetItem(str('wait'))
        item_3 = QTableWidgetItem(str('wait'))
        item_4 = QTableWidgetItem(str('wait'))
        item_5 = QTableWidgetItem(str('wait'))
    
        # execute the line below to every item you need locked
        item.setFlags(QtCore.Qt.ItemIsEnabled)
        item_2.setFlags(QtCore.Qt.ItemIsEnabled)
        item_3.setFlags(QtCore.Qt.ItemIsEnabled)
        item_4.setFlags(QtCore.Qt.ItemIsEnabled)
        item_5.setFlags(QtCore.Qt.ItemIsEnabled)
        
        
        
        table_widget.setItem(0, 1, item)
        table_widget.setItem(1, 1, item_2)
        table_widget.setItem(1, 2, item_3)
        table_widget.setItem(3, 1, item_4)
        table_widget.setItem(4, 1, item_5)
        

        delegate = ReadOnlyDelegate(table_widget)
        table_widget.setItemDelegate(delegate)
        
        

if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(320, 240)
    w.show()
    sys.exit(app.exec_())

In the example above, the cells with items which are un-editable remain that way even though I ran the Delegate on the entire table AFTER creating and inserting those items. Is there a way to make the entire table including the un-editable cells editable?


Solution

  • Model approach solves this kind of problems in easy way: you can specify flags for specific items or whole table as function of

    from PyQt5 import QtWidgets, QtCore, QtGui
    
    class Model(QtGui.QStandardItemModel):
    
        def __init__(self, rows, columns, parent = None):
            super().__init__(rows, columns, parent)
            self._editable = True
    
        def flags(self, index: QtCore.QModelIndex) -> QtCore.Qt.ItemFlags:
            flags = super().flags(index)
            if not self._editable:
                flags = flags &~ QtCore.Qt.ItemIsEditable
            return flags
    
        def setEditable(self, editable):
            self._editable = editable
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication([])
    
        model = Model(4, 3)
    
        widget = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout()
        
        view = QtWidgets.QTableView()
        view.setModel(model)
        view.show()
    
        checkBox = QtWidgets.QCheckBox("Editable")
        checkBox.setChecked(True)
        checkBox.clicked.connect(model.setEditable)
    
        layout.addWidget(view)
        layout.addWidget(checkBox)
        widget.setLayout(layout)
        widget.show()
        
        app.exec()