2009年11月24日

[QT]用 QTableView 解決資料過多, 顯示速度太慢的問題

在QT中, 有一個很方便的 class 可以使用來呈現 Table 表格資料: QTableWidget,但是如果在資料很多的情況, 如有幾萬筆的資料時, 使用QTableWidget 會造成 CPU 負載過高,整個應用程式好像 crash 一樣..

如果只有幾千筆的資料, 可以在 insert data前後使用底下的方式, 讓QTableWidget 先暫停 redraw


ui.tableWidget->setUpdatesEnabled(false);
ui.tableWidget->setRowCount( .... );

...
QTableWidgetItem *item = new QTableWidgetItem;
item->setText(ret.value(sql_header[i]));
item->setFlags(Qt::ItemIsEnabled);
ui.tableWidget->setItem(row,col++,item);
...

ui.tableWidget->setUpdatesEnabled(true);



但是當資料超過1萬筆之後, 只能使用 QTableView 來解決此問題, 使用 QTableView 的方式可以看QT Help裏的 Model/View programming 章節, 底下簡單列出繼承 QTableView 之後, 最基本必須要覆載的函式, 讓 QTableView 能呈現資料

1.準備 model
1.1繼承 QAbstractTableModel
1.2覆載

int rowCount(const QModelIndex & parent = QModelIndex() ) const;
int columnCount(const QModelIndex & parent = QModelIndex() ) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole ) const;
QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const ;


2.將此 model 給 QTableView (QLogData為我們繼承自 QAbstractTableModel 的class)

QLogData *sqlDataModel = new QLogData;
ui.tableView->setModel(sqlDataModel);


2.1每當 model 有變化時, QTableView 自然會知道, 因為 QTableView的資料來源就是 Model
2.2在 setModel() 前後再加上 setUpdatesEnabled()會更快

3.可以想像成我們是一次塞資料給 QTableWidget, 而 QTableView 則只會去抓現在元件呈現的區域所需的資料, 如使用者拉捲軸時, QTableView 便會去跟 Model 要目前所需的 row/column 的資料
3.1 另外resizeColumnsToContents() 這函式你也許會用到