Search code examples
pythonpyqtpyqt4qtablewidgetqtablewidgetitem

Why QTableWidgetItem doesn't keep updating it's color?


I have a QTableWidget in my program. I want it's rows and columns to change color according to the time entry in the table widget. When I first add the time, it's compared to current system time and the color changing does take effect but as time goes by it doesn't keep up and the colors remain the same. I want it to keep updating table item's color. I cant include all the code as it is too long but I have included the relevant part.

#Operations_Tree is the QTABLEWIDGET
def Scheduler_Loop(self):
    Timer = QtCore.QTimer(self)
    Timer.start(1000)
    Timer.timeout.connect(self.test)

def test(self):

    time = QtCore.QTime.currentTime()
    current_time_text = time.toString('hh:mm:ss')
    for row in range(0,self.Operations_Tree.rowCount()):
        time = self.Operations_Tree.item(row,1)
        time_text = time.text()
        #print(time_text)
        if time_text >= current_time_text :
            for column in range(0,6):
                #print("TEST")
                try:
                    table_widget_item = self.Operations_Tree.item(row, column)
                    table_widget_item.setForeground(QtGui.QColor(0,0,255)) #BLue
                    table_widget_item.setBackground(QtGui.QColor(238,233,233)) #
                    table_widget_item.viewport.update()
                except AttributeError:
                    pass
        else:
            for column in range(0,6):
                #print("TEST")
                try:
                    table_widget_item = self.Operations_Tree.item(row, column)
                    #table_widget_item.setForeground(QtGui.QColor(0,255,0)) #
                    table_widget_item.setBackground(QtGui.QColor(238,233,233)) #
                    table_widget_item.viewport.update()
                except AttributeError:
                    pass
    self.Operations_Tree.update()  

here is a snap of my program:

enter image description here


Solution

  • For me the main problem is that you are comparing strings instead of time, also in Qt it is not necessary to use try-except since many times they hide errors and waste unnecessary resources, it is better to verify.

    PyQt5:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
            self.lcd_number = QtWidgets.QLCDNumber()
            self.lcd_number.setFrameShape(QtWidgets.QFrame.NoFrame)
            self.lcd_number.setFixedHeight(100)
            self.lcd_number.setDigitCount(8)
            self.Operations_Tree = QtWidgets.QTableWidget()
            self.Operations_Tree.setColumnCount(6)
            labels = ["On AIR", "TIME", "ITEM", "DURATION", "B.ITEM", "B.I.DURATION"]
            self.Operations_Tree.setHorizontalHeaderLabels(labels)
    
            lay = QtWidgets.QVBoxLayout(self)
            lay.addWidget(self.lcd_number)
            lay.addWidget(self.Operations_Tree)
    
            for i, t in enumerate(("10:10:10", "12:12:12")):
                self.Operations_Tree.insertRow(self.Operations_Tree.rowCount())
                it = QtWidgets.QTableWidgetItem(t)
                self.Operations_Tree.setItem(i, 1, it)
    
            self.resize(640, 480)
            self.Scheduler_Loop()
    
        def Scheduler_Loop(self):
            Timer = QtCore.QTimer(self)
            Timer.timeout.connect(self.test)
            Timer.start(1000)
            self.test()
    
        @QtCore.pyqtSlot()
        def test(self):
            time = QtCore.QTime.currentTime()
            self.lcd_number.display(time.toString())
            for row in range(self.Operations_Tree.rowCount()):
                it = self.Operations_Tree.item(row, 1)
                r_time = QtCore.QTime.fromString(it.text(), "h:mm:ss")
                flag = r_time >= time
                f_color = QtGui.QColor(0, 0, 255) if flag else QtGui.QColor(0, 255, 0)
                b_color = QtGui.QColor(238, 233, 233) if flag else QtGui.QColor(238,233,233)
                for column in range(0, 6):
                    it = self.Operations_Tree.item(row, column)
                    if it is None:
                        it = QtWidgets.QTableWidgetItem()
                        self.Operations_Tree.setItem(row, column, it)
                    it.setForeground(f_color)
                    it.setBackground(b_color)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    PyQt4:

    from PyQt4 import QtCore, QtGui
    
    
    class Widget(QtGui.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
            self.lcd_number = QtGui.QLCDNumber()
            self.lcd_number.setFrameShape(QtGui.QFrame.NoFrame)
            self.lcd_number.setFixedHeight(100)
            self.lcd_number.setDigitCount(8)
            self.Operations_Tree = QtGui.QTableWidget()
            self.Operations_Tree.setColumnCount(6)
            labels = ["On AIR", "TIME", "ITEM", "DURATION", "B.ITEM", "B.I.DURATION"]
            self.Operations_Tree.setHorizontalHeaderLabels(labels)
    
            lay = QtGui.QVBoxLayout(self)
            lay.addWidget(self.lcd_number)
            lay.addWidget(self.Operations_Tree)
    
            for i, t in enumerate(("10:10:10", "12:12:12")):
                self.Operations_Tree.insertRow(self.Operations_Tree.rowCount())
                it = QtGui.QTableWidgetItem(t)
                self.Operations_Tree.setItem(i, 1, it)
    
            self.resize(640, 480)
            self.Scheduler_Loop()
    
        def Scheduler_Loop(self):
            Timer = QtCore.QTimer(self)
            Timer.timeout.connect(self.test)
            Timer.start(1000)
            self.test()
    
        @QtCore.pyqtSlot()
        def test(self):
            time = QtCore.QTime.currentTime()
            self.lcd_number.display(time.toString())
            for row in range(self.Operations_Tree.rowCount()):
                it = self.Operations_Tree.item(row, 1)
                r_time = QtCore.QTime.fromString(it.text(), "h:mm:ss")
                flag = r_time >= time
                f_color = QtGui.QColor(0, 0, 255) if flag else QtGui.QColor(0, 255, 0)
                b_color = QtGui.QColor(238, 233, 233) if flag else QtGui.QColor(238,233,233)
                for column in range(0, 6):
                    it = self.Operations_Tree.item(row, column)
                    if it is None:
                        it = QtGui.QTableWidgetItem()
                        self.Operations_Tree.setItem(row, column, it)
                    it.setForeground(f_color)
                    it.setBackground(b_color)
    
    if __name__ == '__main__':
        import sys
        app = QtGui.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())