2011-08-18 472 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

它不幸對我的情況沒有幫助,我需要在添加行時更新小部件。主要問題是重新繪製太慢.. –