2

I use a QTableWidget as an I/O feature for the user but I want to make it more user friendly and intuitive by disabling the editability of cells which are only for data output.

I can uncheck "Editable" under flags for each individual cell in Qt Designer but as soon as I change the value of a cell with self.table_item.setItem(row, column, QTableWidgetItem(str(value))) the cells is editable again.

This question/answer suggest using self.table_item.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers), but that changes the flag for the whole QTableWidget item and not only one cell.

I've also tried self.table_time.item(row,column).setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers) but I get the traceback 'QTableWidgetItem' object has no attribute 'setEditTriggers'.

.setFlags() seems like the function I do need to use but I don't know how to use this to make something not editable or how to apply it to a single cell.


Question: How can I change the "editable" flag for a individual cell of a QTableWidget in PyQt5 after changing the value of the cells QTableWidgetItem trough .setItem().


You will get extra imaginary internet points if you provide an additional solution to make a whole row un-editable in an elegant way.

GittingGud
  • 315
  • 2
  • 16

1 Answers1

8

You must disable the flag Qt::ItemIsEditable:

from PyQt5 import QtCore, QtWidgets


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

        table_widget = QtWidgets.QTableWidget(4, 3)
        self.setCentralWidget(table_widget)

        it = QtWidgets.QTableWidgetItem("not editable")
        it.setFlags(it.flags() & ~QtCore.Qt.ItemIsEditable)
        table_widget.setItem(1, 1, it)


if __name__ == "__main__":
    import sys

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

If you want to elegantly disable a row or column you can use a delegate where the createEditor method returns None:

from PyQt5 import QtCore, QtWidgets


class ReadOnlyDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        return


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

        table_widget = QtWidgets.QTableWidget(4, 3)
        self.setCentralWidget(table_widget)

        delegate = ReadOnlyDelegate(table_widget)
        table_widget.setItemDelegateForRow(1, delegate)
        # table_widget.setItemDelegateForColumn(1, delegate)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(320, 240)
    w.show()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you very much! This solution works perfectly, is easy to implement and with your example code also understandable. – GittingGud Jul 04 '19 at 08:34