Qt QListWidget性能问题

时间:2011-08-18 07:39:20

标签: qt qt4

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

由于我在整个过程中遇到性能问题,包括显示这些单行消息,我已经运行了一些测试,发现我使用的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,它还需要我为repaint添加processEvents(),事情开始变得非常慢。当您调整窗口高度(以及隐式列表窗口小部件)时,您可以逐字地观察更新速度的变化。

我尝试过使用性能标记,例如在构造函数中添加以下行:

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

这会加快它的速度,但scrollToBottom()不再起作用。

有谁知道如何提高速度?只要他们使用Qt,就可以建议完全不同的方法。

[编辑] 看一下例如Qt Creator的安装对话中的详细信息列表或者如wireshark这样的程序,每秒显示几行都没有问题,我知道自动滚动列表一般可以高速更新。主要问题是:Qt可以实现吗?

2 个答案:

答案 0 :(得分:7)

视图尝试计算每个新项目的个别大小。由于您可能不需要,您可以通过以下方式禁用它并获得一些速度:

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的插入速度似乎随着列表中已有项目的数量而迅速减少。

答案 1 :(得分:2)

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

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

尝试禁用此功能,然后填充列表,然后重新启用它以重新绘制窗口小部件。

我希望这会有所帮助。