2011-08-18 471 views
3

我的应用程序(Qt 4.6)要求我在列表中显示某些消息,该列表在添加新行时总是向下滚动(因此最近的行始终可见)。Qt QListWidget性能问题

由于我在整个过程中遇到了性能问题,包括显示这些单行消息,我运行了一些测试,发现我使用的QListWidget是主要问题。

我创建了一个简单的测试项目,其中包含一个默认列表控件“listWidget”和一个按钮“pushButton”,它可以在单击循环中添加1000个项目。这两个小部件将添加到主窗口的布局中。 这里是在.cpp代码(.H是默认+时隙定义)

#include "MainWindow.h" 
#include "ui_MainWindow.h" 

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this);  
} 

MainWindow::~MainWindow() 
{ 
    delete ui; 
} 

void MainWindow::on_pushButton_released() 
{ 
    for(int iLine = 0; iLine < 1000; iLine++) 
    { 
     ui->listWidget->addItem(
      QString("%1: This is a dummy text") 
      .arg(QString::number(iLine).rightJustified(4, '0')) 
      ); 
     ui->listWidget->scrollToBottom(); 
     QApplication::processEvents(); 
    } 
} 

没有scrollToBottom()的表现是好的,但如果我添加scrollToBottom,这还需要我为一个加processEvents()重绘,事情开始变得非常缓慢。当您调整窗口的高度(以及隐式列表窗口小部件)时,您可以从字面上观察更新速度的变化。

我试着与性能标志玩弄像添加以下线的构造器:

ui->listWidget->setLayoutMode(QListWidget::Batched); 
ui->listWidget->setBatchSize(10); 

此其加速了很多,但scrollToBottom()确实不再起作用。

有没有人有一个想法如何提高速度?只要他们使用Qt,随意建议完全不同的方法。

[编辑] 看看例如Qt Creator安装对话框中的Details列表或者像wireshark这样的程序没有问题,每秒钟显示几行代码,我知道一般情况下可以高速更新自动滚动列表。主要问题是:Qt有可能吗?

回答

5

视图试图计算每个新项目的个体大小。既然你可能不需要,您可以禁用它,并获得一定的速度:

ui->listWidget->setUniformItemSizes(true); 

而且你并不真的需要要么“无论何时添加了一行更新部件”,即使那是在可能的,因为在特定的更新率之上你不会看到任何差异。
所以,你可以使用计时器(QTIME或QElapsedTimer),以限制你实际上滚动的速度,并强制重绘:

void MainWindow::on_pushButton_released() 
{ 
    static QTime rateTimer; 
    rateTimer.start(); 

    for(int iLine = 0; iLine < 50000; iLine++) 
    { 
     ui->listWidget->addItem(
       QString("%1: This is a dummy text") 
       .arg(QString::number(iLine).rightJustified(5, '0')) 
      ); 

     // Limit at 60 updates/s 
     if(rateTimer.elapsed() > 1000/60) { 
      ui->listWidget->scrollToBottom(); 
      QApplication::processEvents(); 
      rateTimer.restart(); 
     } 
    } 
    // For the items added after the last processEvents() 
    ui->listWidget->scrollToBottom(); 
} 

但对于非常大的列表,你可能需要编写自己的模型导出来自QAbstractListModel,因为QListWidget插入速度似乎随着列表中项目的数量而迅速减少。

+0

谢谢一堆!事情是,我已经尝试限制更新,但我总是只写入processEvents()语句的更新限制。原来,如果像你这样的条件是速度巨大的差异,将scrollToBottom()移动到该位置!我认为我的应用程序应该在使用您的方法时获得的速度很好。 –

+1

只要你不使用包装或IconView模式,统一大小的唯一问题似乎是缺少水平滚动条。但是由于QListView只是从一个项目中获得一次大小,所以你可以设置一个委托,这个'sizeHint'函数将返回一个足够大的尺寸来存放最宽的项目。 – alexisdm

+0

我和我的QtListWidget有类似的速度问题,它拿着〜17k项目。 setUniformItemSizes(true)方法大大加快了应用程序的速度!谢谢你的提示。 –

2

我不确定这是否能解决您的问题,但它可能会提供不同的方法。

QWidget有updatesEnabled属性,它允许您控制小部件是否接收绘画事件。

尝试禁用此properyt然后填充您的列表,然后重新启用它来绘制您的小部件。

我希望这会有所帮助。

+0

它不幸对我的情况没有帮助,我需要在添加行时更新小部件。主要问题是重新绘制太慢.. –