将自定义pushButton设置为单元格小部件会消耗很多时间

时间:2014-03-07 09:55:57

标签: performance pyqt4 qtablewidget qpushbutton

我在qTableWidget列9中设置了我的按钮。它包含3个值,因此当它被点击时,它会将带有这些值的信号发送到我的主要触发DoSomething()方法的主要信号。问题是这条线消耗的时间很长self.tableWidget.setCellWidget(i,9, button)。这是我的按钮的代码,PopulateTable()方法输出问题:

class MyPushButton(QtGui.QPushButton):
    def __init__(self, value1, value2, value3, main):
        super(MyPushButton, self).__init__()
        self.__value1   = value1
        self.__value2   = value2
        self.__value3   = value3
        self.__main     = main
        self.connect(self, QtCore.SIGNAL('clicked()'), self, QtCore.SLOT("triggerOutput()"))

    @QtCore.pyqtSlot()
    def triggerOutput(self):
        self.__main.emit(QtCore.SIGNAL("DoSomethingSignal(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), self.__value1 , self.__value2 , self.__value3) 
PopulateTable()中的

class PYQTEmaszForm(QtGui.QMainWindow)方法:

def PopulateTable(self, numberOfRows, rows):

编辑2 vvvvv

    self.tableWidget.setColumnCount(10)
    self.tableWidget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
    self.tableWidget.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
    self.tableWidget.setFocusPolicy(QtCore.Qt.NoFocus)
    self.tableWidget.verticalHeader().hide()
    self.tableWidget.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
#next line was the problem
    #self.tableWidget.verticalHeader().setResizeMode(QtGui.QHeaderView.ResizeToContents)
    self.tableWidget.horizontalHeader().setResizeMode(QtGui.QHeaderView.Fixed)
    self.tableWidget.resizeColumnsToContents()

^^^^^

    self.tableWidget.setVisible(0)
    self.tableWidget.setSortingEnabled(0)
    self.tableWidget.setRowCount(numberOfRows)

    for i in range(0,numberOfRows):
        #I set columns 0-8 here like this self.tableWidget.setItem(i, colNum, QtGui.QTableWidgetItem(rows[i][colNum]))  

        #here is my problem:
        button = MyPushButton(value1, value2, value3, self)# note that tose 3 values I can get only here, in a loop, so I must store them in my button that I use as link
        button.setText("Click to do something")
        startTime = time.time()
        self.tableWidget.setCellWidget(i,9, button)
        print i," self.tableWidget.setCellWidget(i,9, button) time: ", time.time() - startTime

    self.tableWidget.resizeColumnsToContents()
    self.tableWidget.setSortingEnabled(1)
    self.tableWidget.sortByColumn(0,QtCore.Qt.AscendingOrder)
    self.tableWidget.setVisible(1)

每行增加cetCellWidget的时间。这是我获得的325行:

0 self.tableWidget.setCellWidget(i,9, button) time:  0.010999917984
1 self.tableWidget.setCellWidget(i,9, button) time:  0.0119998455048
2 self.tableWidget.setCellWidget(i,9, button) time:  0.0130000114441
3 self.tableWidget.setCellWidget(i,9, button) time:  0.0150001049042
# ....
100 self.tableWidget.setCellWidget(i,9, button) time:  0.141999959946
101 self.tableWidget.setCellWidget(i,9, button) time:  0.134000062943
102 self.tableWidget.setCellWidget(i,9, button) time:  0.144999980927
103 self.tableWidget.setCellWidget(i,9, button) time:  0.151000022888
# ....
321 self.tableWidget.setCellWidget(i,9, button) time:  0.209000110626
322 self.tableWidget.setCellWidget(i,9, button) time:  0.211999893188
323 self.tableWidget.setCellWidget(i,9, button) time:  0.213000059128
324 self.tableWidget.setCellWidget(i,9, button) time:  0.212000131607

所以填充表持续超过1分钟。

我的问题是为什么setCellWidget需要这么多时间以及为什么时间在增长?

我做错了什么?

EDIT1 我尝试过这样设置简单QPushButtonbutton = QtGui.QPushButton()setCellWidget方法的时间消耗没有差异。所以它不依赖于MyPushButton小部件。

1 个答案:

答案 0 :(得分:2)

问题是setCellWidget只是一种方便的方法:它没有针对在单个表中添加数百个小部件进行优化,因此您看到的性能降低是不可避免的。

要获得最佳性能,您必须创建自定义委托,并使用QStyle在其paint方法中绘制按钮。当然,这也意味着你必须自己实现所有鼠标处理等等。

为了让您了解所涉及的内容,可以找到一些示例代码here

修改

这是一个基于问题中原始代码的测试脚本。对我来说,这在325行内完成了几分之一秒:

import time
from PyQt4 import QtCore, QtGui

class MyPushButton(QtGui.QPushButton):
    def __init__(self, value1, value2, value3, main):
        super(MyPushButton, self).__init__()
        self.__value1   = value1
        self.__value2   = value2
        self.__value3   = value3
        self.__main     = main
        self.connect(self, QtCore.SIGNAL('clicked()'), self, QtCore.SLOT("triggerOutput()"))

    @QtCore.pyqtSlot()
    def triggerOutput(self):
        self.__main.emit(QtCore.SIGNAL("DoSomethingSignal(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), self.__value1 , self.__value2 , self.__value3)

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.table = QtGui.QTableWidget(self)
        self.button = QtGui.QPushButton('Populate', self)
        self.button.clicked.connect(self.handleButton)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.table)
        layout.addWidget(self.button)

    def handleButton(self):
        self.populateTable(325)

    def populateTable(self, numberOfRows):
        self.table.setVisible(0)
        self.table.setSortingEnabled(0)
        self.table.setRowCount(numberOfRows)
        self.table.setColumnCount(10)

        for i in range(0, numberOfRows):
            for colNum in range(10):
                text = 'Text(%d, %d)' % (i, colNum)
                self.table.setItem(i, colNum, QtGui.QTableWidgetItem(text))
            button = MyPushButton(1, 2, 3, self)
            button.setText("Click")
            startTime = time.time()
            self.table.setCellWidget(i,9, button)
            print i," self.tableWidget.setCellWidget(i,9, button) time: ", time.time() - startTime

        self.table.resizeColumnsToContents()
        self.table.setSortingEnabled(1)
        self.table.sortByColumn(0, QtCore.Qt.AscendingOrder)
        self.table.setVisible(1)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 300, 1000, 600)
    window.show()
    sys.exit(app.exec_())

<强>更新

我不确定完全你想要什么,但是可以通过在填充表格之前将resize-mode设置为Fixed来解决行调整大小问题,然后设置它之后到ResizeToContents

    ...
    self.tableWidget.horizontalHeader().setResizeMode(QtGui.QHeaderView.Fixed)
    self.tableWidget.verticalHeader().setResizeMode(QtGui.QHeaderView.Fixed)

    # populate table

    self.table.verticalHeader().setResizeMode(QtGui.QHeaderView.ResizeToContents)
    self.table.resizeColumnsToContents()
    self.tableWidget.setSortingEnabled(1)
    self.tableWidget.sortByColumn(0, QtCore.Qt.AscendingOrder)