我在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):
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
小部件。
答案 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)