用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等其他的類本人沒測試。按道理來說,應該也是有效的。
