Search code examples
pythonpyqtpyqt5qtablewidget

Sending a signal to highlight cell in QtableWidget PyQt


In my application, I want to check every cell in a specific column for empty fields. If empty, I would like to highlight the cell. When that cell has been changed, I want to unhighlight it. The code below works, but will stop highlighting altogether after the function highlights something twice. Please tell me why this happens and how to fix this code.

def getAllTableValues(self):
    for index in range(self.rowCount()):
        item = self.item(index,2)
        if item.text() == "":
            item.setBackground(QtCore.Qt.red)
            self.itemChanged.connect(lambda: self.changeToWhite(item))
            return None
    allRows = self.getAllRows()

def changeToWhite(self, item):
    item.setBackground(QtCore.Qt.white)

Edit: It seems that QwidgetItem will stop highlighting all together after it has been highlighted twice. Other cells will continue to highlight until highlighted twice.


Solution

  • itemChanged is called every time the item is modified although the modification will clean the cell. A better option is to use a delegate that changes the color according to the text shown:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class HighlightDelegate(QtWidgets.QStyledItemDelegate):
        def initStyleOption(self, option, index):
            super(HighlightDelegate, self).initStyleOption(option, index)
            color = QtGui.QColor(QtCore.Qt.white if option.text else QtCore.Qt.red)
            option.backgroundBrush = QtGui.QBrush(color)
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            table = QtWidgets.QTableWidget(10, 10)
            delegate = HighlightDelegate(table)
            table.setItemDelegateForColumn(2, delegate)
    
            self.setCentralWidget(table)
    
    
    if __name__ == '__main__':
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())