Проблемы с производительностью Qt QListWidget - PullRequest
3 голосов
/ 18 августа 2011

мое приложение (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?

Ответы [ 2 ]

7 голосов
/ 19 августа 2011

Представление пытается вычислить индивидуальный размер каждого нового элемента. Поскольку вам это, вероятно, не нужно, вы можете отключить его и набрать некоторую скорость с помощью:

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, по-видимому, быстро уменьшается с числом элементов в списке.

2 голосов
/ 18 августа 2011

Я не уверен, решит ли это вашу проблему или нет, но может предложить другой подход.

QWidget имеет updatesEnabled свойство, которое позволяет вам контролировать, получает ли виджет события рисования или нет.

Попробуйте отключить эту собственность, затем заполните свой список и затем включите его, чтобы нарисовать ваш виджет обратно.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...