python - qtablewidgetitem pyqt
PyQT QTableWidget extremadamente lento (2)
este es el código que uso para llenar una tabla dibujada en QT Designer. Diseñado para ser universal para cualquier mesa, funciona bien, pero ... Cuando intento mostrar un datasat que contiene 18 columnas y ~ 12000 filas, simplemente se congela durante 30 segundos o más. Entonces, ¿qué estoy haciendo mal y hay forma de acelerar, manteniendo el código aún adecuado para cualquier mesa?
Ese es mi código:
...blablabla...
self.connect(self, SIGNAL("set"), self.real_set)
...blablabla...
def set_table(self, table, data):
self.emit(SIGNAL(''set''), table, data)
def real_set(self, table, data):
"""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Assuming data is list of dict and table is a QTableWidget.
Get first key and get len of contents
"""
for key in data:
rows = len(data[key])
table.setRowCount(rows)
break
"""
Forbid resizing(speeds up)
"""
table.horizontalHeader().setResizeMode(QHeaderView.Fixed)
table.verticalHeader().setResizeMode(QHeaderView.Fixed)
table.horizontalHeader().setStretchLastSection(False)
table.verticalHeader().setStretchLastSection(False)
"""
Set number of columns too
"""
table.setColumnCount(len(data))
table.setHorizontalHeaderLabels(sorted(data.keys()))
"""
Now fill data
"""
for n, key in enumerate(sorted(data.keys())):
for m, item in enumerate(data[key]):
newitem = QTableWidgetItem(item)
table.setItem(m, n, newitem)
Aquí un script de prueba que compara algunas formas de llenar una tabla.
El modelo personalizado es mucho más rápido, porque no tiene que crear todos los elementos por adelantado, pero tenga en cuenta que es una implementación muy básica, por lo que no implementa clasificación, edición, etc. (Consulte la Programación de modelo / vista para obtener más detalles) .
from random import shuffle
from PyQt4 import QtCore, QtGui
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data, parent=None):
super(TableModel, self).__init__(parent)
self._data = data
def rowCount(self, parent=None):
return len(self._data)
def columnCount(self, parent=None):
return len(self._data[0]) if self.rowCount() else 0
def data(self, index, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
row = index.row()
if 0 <= row < self.rowCount():
column = index.column()
if 0 <= column < self.columnCount():
return self._data[row][column]
class Window(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 = []
def populateTable(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 is not None:
self.table.setModel(None)
model.deleteLater()
if len(self._data) != self.spinbox.value():
del self._data[:]
rows = list(range(self.spinbox.value()))
shuffle(rows)
for row in rows:
items = []
for column in range(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 in enumerate(self._data):
for column, text in enumerate(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_())
En las aplicaciones de GUI, uno se encuentra con una situación en la que es necesario mostrar una gran cantidad de elementos en un formato tabular o de lista (por ejemplo, muestra una gran cantidad de filas en una tabla). Una forma de aumentar la capacidad de respuesta de la GUI es cargar algunos elementos cuando se muestra la pantalla y posponer la carga del resto de los elementos en función de la acción del usuario. Qt proporciona una solución para abordar este requisito de cargar los datos a pedido.
Puede encontrar la implementación de esta técnica llamada paginación en este enlace