QT中Qtableview視圖表格中點擊表頭進行排序


用QT寫了一個小工具,主要是對Excel中大量的數據進行計算和顯示。

寫了有一段時間,然后斷斷續續的做一些修改和完善。

因為要顯示的數據有多列,很自然的會想到要能夠對顯示的數據進行排序。如果直接操作model里的數據,不太方便,因為最好是能由用戶自己選擇按哪一列進行排序。如果通過信號槽機制,也不是很方便。然后找到QTableView下有一個setSortingEnabled()的函數。在將該函數設置為True后,在鼠標移動到表頭上某一列時,可以看到出現了可以用於提示點擊的上三角或下三角標志,但是,在鼠標點擊過后沒有任何反應。本人以為上述函數被設置為True后,還要對每一列的排序用代碼實現,想想就發怵,作罷。后來繼續研究,說是可以通過信號槽,先獲取鼠標點擊表頭的信號,然后映射到一個sortByColumn()的排序槽函數上,用於排序。因為本人對信號槽也只是入門,編寫起來發現也有一些問題不好解決。最后在中文網上幾乎找不到好的解決辦法,關鍵是並沒有相關度很高的內容。於是,就試着用了一下google。一會就找到了好幾個類似的問題,網友也提出了幾種解決方案。

首先說一下原因:

將setSortingEnabled()函數設為True后,點擊表頭排序的背后調用的是sortByColumn()這個函數。

在qtableview.cpp源文件中有sortByColumn()函數的實現代碼:

 1 void QTableView::sortByColumn(int column)
 2 {
 3     Q_D(QTableView);
 4 
 5     if (!d->model)
 6         return;
 7     bool ascending = (horizontalHeader()->sortIndicatorSection()==column&& horizontalHeader()->sortIndicatorOrder()==Qt::DescendingOrder);
 8     Qt::SortOrder order = ascending ? Qt::AscendingOrder : Qt::DescendingOrder;
 9     horizontalHeader()->setSortIndicator(column, order);
10     d->model->sort(column, order);
11 }

sortByColumn()函數最后調用的model的sort函數。

由於本人使用的model類型是QSqlQueryModel,該類型繼承自QAbstractTableModel類,而該類又繼承自QAbstractItemModel。

QSqlQueryModel和QAbstractTableModel這兩個類本身是沒有sort函數的,自能使用QAbstractItemModel類的sort函數。

QAbstractItemModel類中的sort函數形式如下:

virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder)

它是一個虛擬函數,也就是說沒有具體的實現,是無法真正用於排序的。

所以由此產生一個思路,如果將model的類型轉換成一個重寫了sort函數的model類,那么也許就可以通過點擊表頭進行排序了。

找一下QAbstractItemModel有哪些子類,通過一番搜索,找到QAbstractProxyModel、QSqlTableModel等子類都有重寫的sort函數。

我們把之前QSqlQueryModel的model轉換為QAbstractProxyModel試一下,看是否有效。

1 QSqlDatabase db_output1 = QSqlDatabase::database("db_output1_connection");
2 QSqlQueryModel *model = new QSqlQueryModel();
3 QString model_query;
4 model_query = QString("Select Airline ,Airline1, Ratio, Angle, Year, Summer, Winter from [%1$]").arg(show_sheet_name);
5 model->setQuery(model_query,db_output1);
6 QSortFilterProxyModel *sqlproxy = new QSortFilterProxyModel(this);
7 sqlproxy->setSourceModel(model);
8 ui->tableView->setModel(sqlproxy);

 

這是沒有排序時,顯示的結果。

上圖是單擊表頭中的日班次后排序的結果。

上圖是單擊另一列的表頭(費率)后排序的結果。其他各列的排序也均有效。

QSqlTableModel等其他的類本人沒測試。按道理來說,應該也是有效的。

一點感悟:

遇到技術問題,要善於將問題准確提煉出來,是自己搜索也好,或是請教他人都有幫助。往往是對遇到的問題迷迷糊糊,沒有經過仔細思考,導致不知從何處開始解決,最后半途而廢。

國內的圈子必然有限,多用google。

附幾個相關問題的鏈接:

http://www.qtcentre.org/archive/index.php/t-467.html

http://www.qtforum.org/article/18679/qsqlquerymodel-qtableview-and-sorting.html

http://www.qtforum.org/article/26898/how-to-sort-data-by-column-in-a-table-view-model-set-for-table-view-is-qsqlquerymodel-if-click-to-headerview.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM