QListWidgetItem setter functions in PyQt5 are very slow?



  • Hello, I just want to preface this by saying this is my first time posting, any feedback will be appreciated.

    This is a simple representation of the problem, I am using a QTableWidget and the variable cell is a QTableWidgetItem. I am trying to change the background color of about 400 QTableWidgetItems in a QTableWidget, I am using setBackground but have also tried setData and setFont with the same results.

    color = QtGui.QColor()
    column = 3
    for row in rowIndexList:
        cell = table.item(row,column)
        color.setNamedColor('#00ff00')
        start = time.time()
        cell.setBackground(color)
        end = time.time()
        print('time to set background' + str(end-start))
    

    The print statement from this code will print about 0.13-0.15 seconds for every iteration, and this loop iterates 400 times. Is there a reason the setBackground function for the QTableWidgetItem is so slow? Do I need to use a QTableView with delegates because of this?

    Here is some output I set up for my program
    0_1499366718074_output.png


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Part of this is likely due to the fact that you'll trigger a repaint for the whole widget each time you change an item background colour.

    You could disable the updates from your view. Update your model and then enable the updates again.

    Note that there's no need to set the colour of your color variable for each index. You can do it before your for loop.



  • I see, thanks for the reply; you are right about the color variable. I wrote the code snippet quickly, in the actual function the variable possibly changes with every loop and is not hard coded to '#00ff00'.

    I will attempt to replace my qtablewidget with a qtableview and custom model, then I will respond back with the results.



  • I modified the code to be

    class CustomTableView(QTableView):
        def __init__(self,parent=None):
            super().__init__(parent)
    
    class CustomStandardModel(QtGui.QStandardItemModel):
        def __init__(self,parent=None):
            super().__init__(parent)
    
    class CustomStandardItem(QtGui.QStandardItem):
        def __init__(self,parent=None):
            super().__init__(parent)
    
    table = CustomTableView()
    model = CustomStandardModel()
    table.setModel(model)
    
    /...
    #fill the model with CustomStandardItem objects
    .../
    
    color = QtGui.QColor()
    color.setNamedColor('#00ff00')
    column = 3
    for row in rowIndexList:
        cell = model.item(row,column)
        start = time.time()
        cell.setBackground(color)
        end = time.time()
        print('time to set background' + str(end-start))
    

    And this is significantly faster than the qtablewidget.

    output:
    0_1499375234983_Screen Shot 2017-07-06 at 2.06.59 PM.png

    EDIT:
    This loop for setting columns to autoresize was causing the initial problem of setBackground taking so long, with it commented out the QTableWidget is as fast as the QTableView. This loop runs once after the table is loaded with values, however every time setBackground is called it is affected.

    for col in range(self.columnCount()):   
         self.horizontalHeader().setSectionResizeMode(col,QHeaderView.ResizeToContents)
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.