performance - 将自定义按钮设置为单元格小部件会消耗大量时间

标签 performance pyqt4 qtablewidget qpushbutton

我在 qTableWidget 中设置了按钮第 9 列。它包含 3 个值,因此当单击它时,它会向我的 main 发送包含这些值的信号,从而触发 DoSomething()方法在我的 main.问题是这条线消耗了很多时间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 我尝试过设置简单 QPushButton像这样:button = QtGui.QPushButton() ,并且setCellWidget的时间消耗没有差异。方法。所以它不取决于 MyPushButton小部件。

最佳答案

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

为了获得最佳性能,您必须创建一个自定义委托(delegate)并使用 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_())

更新:

我不确定到底你想要什么,但是行调整大小问题可能可以通过在填充表格之前将调整大小模式设置为固定来解决,并且然后将其设置为 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)

关于performance - 将自定义按钮设置为单元格小部件会消耗大量时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22246824/

相关文章:

c - Windows 中进程的最短保证时间是多少?

Qt - 如何在顶部而不是底部显示 tabified dockwidget 的选项卡

c++ - Qt4 QTableWidget 使 Column resize to contents, interactive and aligned to table border

python - PyQt 5 QTableWidget.cellClicked 信号不工作

performance - 空数据库的 RavenDB 慢查询

database - 如何提高 MonetDB 单节点查询性能?

bash - 如何有效地列出正好有 `n` 行的文件?

javascript - 使用 beautifulsoup python 调用 onclick 事件

python - PyQt 窗口未显示在屏幕上

python - 检索选定的记录