用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