Pyqt Qtablewidget Extremely Slow
Solution 1:
Here a test script which compares a few ways of populating a table.
The custom model is much faster, because it does not have to create all the items up front - but note that it is a very basic implementation, so does not implement sorting, editing, etc. (See Model/View Programming for more details).
from random import shuffle
from PyQt4 import QtCore, QtGui
classTableModel(QtCore.QAbstractTableModel):
def__init__(self, data, parent=None):
super(TableModel, self).__init__(parent)
self._data = data
defrowCount(self, parent=None):
returnlen(self._data)
defcolumnCount(self, parent=None):
returnlen(self._data[0]) if self.rowCount() else0defdata(self, index, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
row = index.row()
if0 <= row < self.rowCount():
column = index.column()
if0 <= column < self.columnCount():
return self._data[row][column]
classWindow(QtGui.QWidget):
def__init__(self):
super(Window, self).__init__()
self.table = QtGui.QTableView(self)
self.tablewidget = QtGui.QTableWidget(self)
self.tablewidget.setSortingEnabled(True)
self.button1 = QtGui.QPushButton('Custom Model', self)
self.button1.clicked.connect(
lambda: self.populateTable('custom'))
self.button2 = QtGui.QPushButton('StandardItem Model', self)
self.button2.clicked.connect(
lambda: self.populateTable('standard'))
self.button3 = QtGui.QPushButton('TableWidget', self)
self.button3.clicked.connect(
lambda: self.populateTable('widget'))
self.spinbox = QtGui.QSpinBox(self)
self.spinbox.setRange(15000, 1000000)
self.spinbox.setSingleStep(10000)
layout = QtGui.QGridLayout(self)
layout.addWidget(self.table, 0, 0, 1, 4)
layout.addWidget(self.tablewidget, 1, 0, 1, 4)
layout.addWidget(self.button1, 2, 0)
layout.addWidget(self.button2, 2, 1)
layout.addWidget(self.button3, 2, 2)
layout.addWidget(self.spinbox, 2, 3)
self._data = []
defpopulateTable(self, mode):
if mode == 'widget':
self.tablewidget.clear()
self.tablewidget.setRowCount(self.spinbox.value())
self.tablewidget.setColumnCount(20)
else:
model = self.table.model()
if model isnotNone:
self.table.setModel(None)
model.deleteLater()
iflen(self._data) != self.spinbox.value():
del self._data[:]
rows = list(range(self.spinbox.value()))
shuffle(rows)
for row in rows:
items = []
for column inrange(20):
items.append('(%d, %d)' % (row, column))
self._data.append(items)
timer = QtCore.QElapsedTimer()
timer.start()
if mode == 'widget':
self.tablewidget.setSortingEnabled(False)
for row, items inenumerate(self._data):
for column, text inenumerate(items):
item = QtGui.QTableWidgetItem(text)
self.tablewidget.setItem(row, column, item)
self.tablewidget.sortByColumn(0, QtCore.Qt.AscendingOrder)
else:
self.table.setSortingEnabled(False)
if mode == 'custom':
model = TableModel(self._data, self.table)
elif mode == 'standard':
model = QtGui.QStandardItemModel(self.table)
for row in self._data:
items = []
for column in row:
items.append(QtGui.QStandardItem(column))
model.appendRow(items)
self.table.setModel(model)
self.table.setSortingEnabled(True)
self.table.sortByColumn(0, QtCore.Qt.AscendingOrder)
print('%s: %.3g seconds' % (mode, timer.elapsed() / 1000))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 50, 1200, 800)
window.show()
sys.exit(app.exec_())
Solution 2:
In GUI applications one comes across a situation where there is a need to display a lot of items in a tabular or list format (for example displaying large number of rows in a table). One way to increase the GUI responsiveness is to load a few items when the screen is displayed and defer loading of rest of the items based on user action. Qt provides a solution to address this requirement of loading the data on demand.
You can find the implementation of this technique called pagination in this link
Post a Comment for "Pyqt Qtablewidget Extremely Slow"