C++ QTableView在一次可以看到多个单元格时滚动缓慢

C++ QTableView在一次可以看到多个单元格时滚动缓慢,c++,performance,qt,qtableview,C++,Performance,Qt,Qtableview,背景:我正在使用Qt 5.5.1开发应用程序,并使用msvc2013进行编译。在这个应用程序中,我使用我自己的QTableView实现,以及定制的QStyledItemDelegate(需要定制单元格编辑)和QAbstractTableModel。我希望这个视图能够处理我在上述模型中封装的大量数据。我允许用户使用很少的数据编辑选项、自定义排序、“无效”行结束等 问题:我的QTableView子类的滚动速度很慢-显示的表格越多(通过调整窗口大小),滚动速度就越慢,例如显示的约250个单元格(全屏)

背景:我正在使用Qt 5.5.1开发应用程序,并使用msvc2013进行编译。在这个应用程序中,我使用我自己的QTableView实现,以及定制的QStyledItemDelegate(需要定制单元格编辑)和QAbstractTableModel。我希望这个视图能够处理我在上述模型中封装的大量数据。我允许用户使用很少的数据编辑选项、自定义排序、“无效”行结束等

问题:我的QTableView子类的滚动速度很慢-显示的表格越多(通过调整窗口大小),滚动速度就越慢,例如显示的约250个单元格(全屏)=慢,显示的约70个单元格(小窗口)=快

到目前为止我尝试了什么:

  • 首先是检查我的模型是否减慢了速度——我测量了读取10k样本的时间(使用QTime::appeased()),结果显示为0或1ms。然后,我简单地修改了QTableView::data方法,使其始终返回预定义的字符串,而不获取任何实际数据

    QVariant数据集_TableModel::数据(常量QModelIndex&index,int角色)常量
    {
    if(角色==Qt::ItemDataRole::DisplayRole){
    return QVariant(“aRatherLongString”);//导致缓慢滚动
    //return QVariant(“a”);//这会导致快速滚动
    }
    否则返回QVariant();
    }
    
    正如您所看到的,速度似乎受每个单元格的字符数的影响,而不是受到数据源的底层连接的影响

  • 在QStyledItemDelegate的自定义实现中,我尝试了与上面相同的“技巧”-这次超出了displayText方法的权限:

    QString数据集\u TableModel\u StyledItemDelegate::displayText(常量QVariant&value,常量QLocale&locale)常量
    {
    返回“a”//fast
    //返回“aRatherLongString”;//慢
    //返回QStyledItemDelegate::displayText(值,区域设置);//默认值
    }

  • 经过与一位朋友的思考,我们得出结论,也许我们可以禁用单元格的绘制/绘制/更新,直到整个滚动动作完成。它可能会引起一些闪烁,但值得一试。不幸的是,我们真的不知道如何解决这个问题。我们有everriden QTableView方法:scrollContentsBy(int-dx,int-dy)和verticalScrollbarAction(int-action)——我们已经正确地捕获了scroll操作(两种方法都截获了它),并尝试以某种方式禁用重新绘制,如下所示:

    void数据集_TableView::verticalScrollbarAction(int操作){
    此->设置日期已启用(false);
    QTableView::垂直滚动条动作(action);
    此->设置日期启用(true);
    }
    

…但没有任何明显的效果。 我们应该如何处理?我们是否需要对直接放入单元格的项使用setUpdatesEnabled()?(不确定这些是什么-小部件?)

以下是测试此问题的部分截图:


请求:您能帮我找出原因并提出解决方案吗?这是我使用的类的限制吗?

首先,您还应该在
release
模式下运行应用程序以检查性能,根据我的经验,使用
debug
模式时,性能会大大降低

其次,您需要注意,每次调整大小、滚动、调出焦点、右键单击等操作都会调用model
data
方法和delegate方法。这些操作会触发为每个显示的单元格调用这些方法,因此您需要确保不进行任何不必要的处理

单元格中的项是调用自己方法的委托(例如:
paint

某些C++特定优化将有助于实现这些方法,如使用<代码>开关<代码>代替<代码> > 语句,请参见解释和。使用条件(三元)运算符还可能加快速度,提供更多信息,以及一些有关昂贵检查的信息

此外,QVariant以不同的方式处理文本,如下例所示,您应该尝试两种方式,并检查速度是否有任何差异。有些转换比其他转换更昂贵

v = QVariant("hello");          // The variant now contains a QByteArray
v = QVariant(tr("hello"));      // The variant now contains a QString

你试过用分析工具分析它吗?没有。我可能会尝试使用探查器,但我还没有学会如何使用它(并找到合适的工具),这需要一些时间。您的项目大小是否都相同?如果是,您是否设置了视图的
uniformItemSizes
属性。这可能会对性能产生相当大的影响。@TobySpeight我确实尝试过这样做,但QTableView没有任何类似于uniformItemSizes的属性(看起来您谈论的是QListView)。我曾尝试在视图的构造函数中的两个标题上使用setDefaultSectionSize(mySize)、setSectionResizeMode(QHeaderView::Fixed)和resizeSections(QHeaderView::Fixed)(按给定顺序)-滚动速度没有任何积极的变化。@Frankosterfield我和一个朋友做了一些分析,得到如下结果:[链接](使用luke stackwalker)-不幸的是,我们目前缺乏从这一结果中得出任何结论的知识。测试只包含滚动动作。一个测试是用空的QVariant完成的,它很快,另一个测试是用QVariant内部的QString完成的——这个测试很慢。