QTableWidget对于大型表来说变得很慢

时间:2018-03-28 07:58:33

标签: python qt pyqt qtableview qtablewidget

我想创建一个Qt表小部件,每秒增加大约20个新行(最大值为10000)。旧行永远不会改变。

首先我使用了QTableWidget,但是我看到CPU%随着表格大小的增加而增加,并且在总共大约1000行时达到100%。

所以我尝试创建自己的模型,每5秒才会生成beginInsertRowsendInsertRows。我希望CPU%会变得不变,因为我只发出 new 行,但我发现它仍然会上升到100%。

所以我检查了我在发出之间获得的data()次呼叫的数量,我看到它等于 240 * total_num_rows

  1. 为什么视图会查询所有行,而不仅仅是新行?
  2. 为什么是240?我每行总共有10列。有24个角色吗?
  3. 我可以以某种方式控制视图以减少查询(常量)吗?
  4. 修改

    项目视图:

    ''' 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
    

1 个答案:

答案 0 :(得分:1)

这是一种解决方法,但将模型限制为row count < 1000会产生恒定的CPU%。

因此,对我来说,一个优雅的解决方案是创建一个“分页”表视图,一次只显示N行(并且用户可以控制当前显示的窗口)。

这会产生出色的CPU以及更好的可用性,因此我认为最初的问题并不相关。