当多个单元格同时可见时,QTableView会慢速滚动

时间:2016-04-24 20:27:18

标签: c++ performance qt qtableview

后台:我正在使用Qt 5.5.1开发应用程序,使用msvc2013进行编译。在这个应用程序中,我使用自己的QTableView实现,以及自定义QStyledItemDelegate(需要自定义单元格编辑)和QAbstractTableModel。我希望这个视图能够处理我提到的模型中包含的大量数据。我允许用户使用少量数据编辑选项,自定义排序,'无效'行结束等。

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

到目前为止我做了什么:

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

    QVariant DataSet_TableModel::data(const QModelIndex &index, int role) const { if (role == Qt::ItemDataRole::DisplayRole) { return QVariant("aRatherLongString"); //results in slow scrolling //return QVariant("a"); // this instead results in fast scrolling } else return QVariant(); } 如您所见,速度似乎受到每个单元格的字符数量的影响,而不受数据源的基础连接的影响。

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

    QString DataSet_TableModel_StyledItemDelegate::displayText(const QVariant &value, const QLocale &locale) const { return "a" //fast // return "aRatherLongString"; //slow // return QStyledItemDelegate::displayText(value, locale); //default }

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

    void DataSet_TableView::verticalScrollbarAction(int action) { this->setUpdatesEnabled(false); QTableView::verticalScrollbarAction(action); this->setUpdatesEnabled(true); }

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

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

Predefined text, no calls to underlying data structure - slow scrolling, 'full screen'

Predefined text, no calls to underlying data structure - fast scrolling, windowed

请求:您是否可以帮助我查明原因并提出解决方案?是否限制了我使用的类?

1 个答案:

答案 0 :(得分:1)

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

其次,您需要注意每次调整大小,滚动,聚焦,右键单击等时都会调用模型debug方法和委托方法。这些操作会触发为每个显示的单元调用这些方法因此,您需要确保不进行任何不必要的处理。

单元格内的项目是调用自己方法的委托(例如:data)。

某些特定于C ++的优化将有助于实现这些方法,例如使用paint而不是switch语句,请参阅解释herehere。条件(三元)运算符的使用也可以加快速度,提供更多信息herehere以及有关昂贵检查的一些信息here

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

if