如何优化QTableView的性能

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何优化QTableView的性能相关的知识,希望对你有一定的参考价值。

参考技术A 1、手动设置定长的表头数据。比如表头可能出现的数据是1到100000,那么我们就以最长的为标准,不够长度的补空格。这样不用需要设置自适应,表格刷新和切换可以瞬间完成。但代价是表头很丑,在数据小时有大片空白2、使用当前最大的表头数据,仅对该数据用QFontMetrics计算宽度,然后对表头设置fixedWidth()。这样理论可行,然而实际很丑陋,调整宽度后多出来的部分只有QWidget底色,文本信息并没有绘制上去,导致表头文本显示不完全,且表头效果绘制错误。然后尝试搜索了"QTableView VerticalHeader width"关键字之后,在Qt论坛搜到一篇帖子,里面给了一个脑洞清奇的解法——设置表头宽度后,将首列宽度设置为0,再重置,即代码如下:ui->tableView->verticalHeader()->setFixedWidth(width);

width = ui->tableView->columnWidth(0);
ui->tableView->setColumnWidth(0, 0);
ui->tableView->setColumnWidth(0, width);
上述代码,会导致表格布局改变,从而触发表格的全局重绘,在这次重绘里,重设宽度过后的表头也能正常显示了。由于所有column和表头都没有设置自适应,所以这个重绘效率很高。最后profile结果如下: - 在设置自适应后,表格刷新耗时10ms内。但若要重新适配表头,则需要耗时10s左右。 - 关闭自适应,通过手动设置fixedWidth方式适配表头,数据刷新加适配表头,总体耗时不超过20ms。
参考技术B https://www.zhihu.com/question/53474393

如何创建 QTableview 单元格悬停功能

【中文标题】如何创建 QTableview 单元格悬停功能【英文标题】:how to create QTableview cell hover function 【发布时间】:2021-12-17 02:32:52 【问题描述】:

我用 QTableview 创建了一个表。我尝试添加鼠标悬停功能(如果我将鼠标放在特定单元格上)以更改光标样式。我无法在 QTableview 中优化任何内置功能鼠标悬停连接功能。所以我用鼠标table.entered.connect(on_entered) 来改变光标。离开功能不可用。所以我面临图片中显示的以下问题。手形光标在单元格(1,1)中发生变化,但离开单元格(1,1)时不会变回箭头

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

data=[[1,1],[1,2],['a','b']]

class TableModel(QAbstractTableModel):
    def __init__(self, data,header_labels=None):
        super().__init__();self._data = data;self.header_labels=header_labels

    def data(self, index, role):
        if role == Qt.DisplayRole:return self._data[index.row()][index.column()]
    def rowCount(self, index):return len(self._data)
    def columnCount(self, index):return len(self._data[0])
    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if self.header_labels==None:self.header_labels=range(len(self._data[0]))
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:return self.header_labels[section]
        return QAbstractTableModel.headerData(self, section, orientation, role)

def on_entered(index):
    if index.row()==1 and index.column()==1: table.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
    else:table.setCursor(QCursor(Qt.CursorShape.ArrowCursor))
app = QApplication(sys.argv)
window = QWidget()
vl=QVBoxLayout(window)

searchbar = QLineEdit()
table=QTableView()
proxy_model = QSortFilterProxyModel()
model = TableModel(data)
proxy_model.setSourceModel(model)
table.setModel(proxy_model)

table.entered.connect(on_entered)
table.setMouseTracking(True)
table.setSelectionMode(QAbstractItemView.NoSelection)
table.setFocusPolicy(Qt.FocusPolicy.NoFocus)

vl.addWidget(table)
t=TableModel(data[1:],data[0])
proxy_model.setSourceModel(t)
window.show()
app.exec_()

【问题讨论】:

【参考方案1】:

您需要对表格进行子类化,覆盖mouseMoveEvent 并使用indexAt 检查鼠标位置处的索引。

由于鼠标移动期间可能会发生鼠标交互,因此您应该仅在按下 no 按钮时设置光标。 mouseTracking 属性仍然是必需的。

class CursorShapeTable(QTableView):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setMouseTracking(True)

    def mouseMoveEvent(self, event):
        super().mouseMoveEvent(event)
        if not event.buttons():
            index = self.indexAt(event.pos())
            if index.row() == 1 and index.column() == 1:
                self.setCursor(Qt.CursorShape.PointingHandCursor)
            else:
                self.unsetCursor()

【讨论】:

这适用于鼠标光标格式。同样,如果我想更改单元格背景颜色而不是光标格式。需要选择哪个选项?如何重置以前的单元格格式? @Viswa 鼠标光标和单元格格式是完全不同的东西。如果您想更改鼠标悬停时单元格的显示方式,那么您需要使用自定义项目委托,但这不是这个问题的主题,所以我建议您: 1. 对 Qt 进行一些研究和学习项目代表,以及 2. 最终提出一个单独的问题。

以上是关于如何优化QTableView的性能的主要内容,如果未能解决你的问题,请参考以下文章

底层模型更改时如何在 QTableView 中禁用自动滚动到顶部?

PyQt4 - QTableView - 如何循环 QTableView

如何更改 QTableView 边框颜色?

QTableView:如何设置搜索栏

QTableView如何设置行高?

如何在调整 QTableView 大小时动态更改列数?