QTableWidget 对于大表变得很慢 [英] QTableWidget becomes slow for large tables
问题描述
我想创建一个 Qt 表小部件,它每秒添加大约 20 行新行(最大为 10000).旧行永远不会改变.
I want to create a Qt table widget which adds about 20 new rows per second (maxed at 10000). Old rows are never changed.
我首先使用 QTableWidget,但我看到 CPU% 随着表大小的增加而增加,并且在总共约 1000 行时达到 100%.
Ar first I used QTableWidget, but I see the CPU% increases as the table size increases, and gets to 100% at around 1000 rows total.
所以我尝试创建自己的模型,它每 5 秒只执行一次 beginInsertRows
和 endInsertRows
.我希望 CPU% 会保持不变,因为我只发出新行,但我看到它仍然上升到 100%.
So I tried to create my own model, which only does beginInsertRows
and endInsertRows
every 5 seconds. I hoped that the CPU% will become constant since I only emit the new rows, but I see that it still climbs up to 100%.
所以我检查了发出之间的 data()
调用的数量,我看到它大约等于 240 * total_num_rows.
So I checked the number of data()
calls I'm getting between emits, and I saw that is equal to about 240 * total_num_rows.
- 为什么视图查询所有的行,而不仅仅是新的行?
- 为什么是 240?我每行总共有 10 列.有 24 个角色吗?
- 我能否以某种方式控制视图以减少查询(常量)?
- Why does the view query all of the rows and not just the new ones?
- Why 240? I have 10 columns total per row. Are there 24 Roles?
- Can I control the view somehow to do less queries (constant)?
编辑
项目视图:
''' How to display each item '''
class BindedItemView(object):
def __init__(self, item):
self._data = item
#--------------------------------------------------------------------#
def _text(self, index):
return QVariant()
#--------------------------------------------------------------------#
def _font(self, index):
return QVariant()
#--------------------------------------------------------------------#
def _background(self, index):
return QVariant()
#--------------------------------------------------------------------#
def _foreground(self, index):
return QVariant()
#--------------------------------------------------------------------#
def get(self, role, col):
if role == Qt.DisplayRole:
return self._text(col)
if role == Qt.FontRole:
return self._font(col)
if role == Qt.ForegroundRole:
return self._foreground(col)
if role == Qt.BackgroundRole:
return self._background(col)
return QVariant()
型号:
class BindedTableModel(QAbstractTableModel):
end_of_process_signal = pyqtSignal()
#--------------------------------------------------------------------#
def __init__(self, headers, item_view):
super(BindedTableModel, self).__init__()
self._headers = headers
self._item_view = item_view
self._items = []
self._last_row_count = 0
self._num_data_requests = 0
#--------------------------------------------------------------------#
def _index(self, item):
return self._items.index(item)
#--------------------------------------------------------------------#
def _indexSorted(self, item):
return bisect.bisect(self._items, item)
#--------------------------------------------------------------------#
def _refreshView(self):
row_count = len(self._items)
print "DATA REQUESTS: %u" % self._num_data_requests
self._num_data_requests = 0
if self._last_row_count < row_count:
print "INSERT ROWS: %u %u" % (self._last_row_count, row_count - 1)
self.beginInsertRows(QModelIndex(), self._last_row_count, row_count - 1)
self.endInsertRows()
# elif self._last_row_count > row_count:
# self.beginRemoveRows(QModelIndex(), row_count, self._last_row_count - 1)
# self.endRemoveRows()
# else:
# top_left = self.createIndex(0, 0)
# bottom_right = self.createIndex(row_count - 1, self.columnCount() - 1)
# self.dataChanged.emit(top_left, bottom_right)
self._last_row_count = row_count
#--------------------------------------------------------------------#
def _onUpdate(self):
pass
#--------------------------------------------------------------------#
def _addItem(self, item, pos):
self._items.insert(pos, item)
self._onUpdate()
#--------------------------------------------------------------------#
def _removeItem(self, pos):
self._items.pop(pos)
self._onUpdate()
#--------------------------------------------------------------------#
def appendItem(self, item):
self._addItem(item, len(self._items))
#--------------------------------------------------------------------#
def addItemSorted(self, item):
self._addItem(item, self._indexSorted(item))
#--------------------------------------------------------------------#
def removeItem(self, item):
self._removeItem(self._index(item))
#--------------------------------------------------------------------#
def clear(self):
self._items = []
#--------------------------------------------------------------------#
def refreshView(self):
self._refreshView()
#--------------------------------------------------------------------#
'''
Override
'''
def rowCount(self, parent = None):
return len(self._items)
#--------------------------------------------------------------------#
'''
Override
'''
def columnCount(self, parent = None):
return len(self._headers)
#--------------------------------------------------------------------#
'''
Override
'''
def data(self, index, role):
self._num_data_requests += 1
item = self._items[index.row()]
view = self._item_view(item)
return view.get(role, index.column())
#--------------------------------------------------------------------#
'''
Override
'''
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return self._headers[section]
return QVariant()
#--------------------------------------------------------------------#
'''
Override
'''
def setData(self, index, value, role):
if role == Qt.DisplayRole:
pass
#--------------------------------------------------------------------#
def __iter__(self):
return self._items.__iter__()
#--------------------------------------------------------------------#
def __contains__(self, item):
return item in self._items
推荐答案
这是一种解决方法,但将模型限制为 行数 <1000
给出了一个恒定的 CPU%.
This is a workaround, but limiting the model to row count < 1000
gives a constant CPU%.
所以对我来说一个优雅的解决方案是创建一个分页"表格视图,它一次只显示 N 行(并且用户可以控制当前显示的窗口).
So an elegant solution for me will be to create a "paged" table view, which only shows N rows at a time (and the user can control the currently displayed window).
这产生了出色的 CPU 以及更好的可用性,所以我认为最初的问题不相关.
This yields excellent CPU as well as better usability, so I think the original question is not relevant.
这篇关于QTableWidget 对于大表变得很慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!