Qt QListWidget性能问题

发布于 2024-11-30 07:50:02 字数 1388 浏览 0 评论 0原文

我的应用程序(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,它还需要我添加 processEvents() 进行重绘,并且事情开始变得非常慢。当您调整窗口(以及隐式列表小部件)的高度时,您可以从字面上观察更新速度的变化。

我尝试过使用性能标志,例如将以下几行添加到构造函数中:

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

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

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

[编辑] 看看 Qt Creator 安装对话框中的详细信息列表或像wireshark这样的程序的性能,它们每秒显示几行没有问题,我知道高速更新的自动滚动列表通常是可能的。主要问题是:这对于 Qt 来说可能吗?

my application (Qt 4.6) requires me to display certain messages in a list which always scrolls down upon adding a new line (so the most recent line is always visible).

As I am having performance issues in the whole process which includes displaying these one-line messages, I've run some tests and found the QListWidget I am using for this to be the main issue.

I've created a simple test project with a default list widget "listWidget" and a push button "pushButton" which adds 1000 items in a loop on click. Those two widgets are added in a layout on the main window.
Here's the .cpp code (.h is default + the slot definition)

#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();
    }
}

Without the scrollToBottom() the performance is alright, but if I add scrollToBottom, it also requires me to add processEvents() for a repaint, and things start getting really slow. When you resize the height of the window (and implicitly the list widget), you can literally watch the update speed changing.

I've tried playing around with performance flags like adding the following lines to the constructor:

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

This speeds it up alot, but scrollToBottom() does no longer work.

Does anyone have an idea how to improve the speed? Feel free to suggest completely different approaches as long as they're using Qt.

[Edit]
Taking a look at the performance of e.g. the Details list in the Install Dialogue of Qt Creator or programs like wireshark which don't have problems displaying a couple of lines per second, I know autoscrolling lists which update at a high speed are possible in general. The main question is: Is this possible with Qt?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

惟欲睡 2024-12-07 07:50:02

该视图尝试计算每个新项目的单独大小。因为您可能不需要它,所以您可以禁用它并获得一些速度:

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

The view tries to calculate the individual size of each new item. Since you probably don't need that, you can disable it and gain some speed with:

ui->listWidget->setUniformItemSizes(true);

And you don't really need either to "update the widget whenever a line is added", even if that was possible, because you won't see any difference above a certain update rate.
So, you can use a timer (QTime or QElapsedTimer) to limit the rate at which you actually scroll and force a repaint:

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();
}

But for very large lists, you might have to write your own model derived from QAbstractListModel, because QListWidget insertion speed seems to decrease rapidly with the number of item already in the list.

吾家有女初长成 2024-12-07 07:50:02

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

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

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

我希望这有帮助。

I am not sure if this will solve your problem or not but it may offer a different approach.

QWidget has updatesEnabled property that allows your control whether widget receives paint events or not.

Try disabling this properyt then populate your list and then re-enable it to paint your widget back.

I hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文