Qt之QHeaderView排序
簡述
在Windows中我們經常會遇到表頭排序,比如可以對文件按照名稱、修改日期、類型、大小進行排序,方便我們統一的歸類查找。
Qt中,我們可以通過點擊表頭來對QTableView或QTreeView等一系列高級視圖進行排序,對于一般的數據來說-比如:int、QString等,簡單的幾句代碼就可以搞定,因為Qt內部做了很好的排序處理,但是一般情況下,我們需要處理一些特殊格式的數據,這時,我們就不得不自己處理,以達到理想的效果。
- 簡述
- 效果
- 自定義數據
- QAbstractTableModel
- 源碼
- 接口說明
- 使用
- 思考
效果
自定義數據
定義各列數據及結構體
#define FILE_NAME_COLUMN 0 // 文件名 #define DATE_TIME_COLUMN 1 // 修改日期 #define FILE_SIZE_COLUMN 2 // 文件大小typedef struct FileRecord {QString strFileName; // 文件名QDateTime dateTime; // 修改日期qint64 nSize; // 文件大小 } fileRecord;QAbstractTableModel
源碼
自定義模型
TableModel::TableModel(QObject *parent): QAbstractTableModel(parent) {}TableModel::~TableModel() {}// 更新表格數據 void TableModel::updateData(QList<FileRecord> recordList) {m_recordList = recordList;beginResetModel();endResetModel(); }// 行數 int TableModel::rowCount(const QModelIndex &parent) const {Q_UNUSED(parent);return m_recordList.count(); }// 列數 int TableModel::columnCount(const QModelIndex &parent) const {Q_UNUSED(parent);return 3; }// 設置表格項數據 bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role) {if (!index.isValid())return false;int nColumn = index.column();FileRecord record = m_recordList.at(index.row());switch (role){case Qt::DisplayRole:{if (nColumn == FILE_NAME_COLUMN){record.strFileName = value.toString();}else if (nColumn == DATE_TIME_COLUMN){record.dateTime = value.toDateTime();}else if (nColumn == FILE_SIZE_COLUMN){record.nSize = value.toLongLong();}m_recordList.replace(index.row(), record);emit dataChanged(index, index);return true;}default:return false;}return false; }// 表格項數據 QVariant TableModel::data(const QModelIndex &index, int role) const {if (!index.isValid())return QVariant();int nRow = index.row();int nColumn = index.column();FileRecord record = m_recordList.at(nRow);switch (role){case Qt::TextColorRole:return QColor(Qt::white);case Qt::TextAlignmentRole:return QVariant(Qt::AlignLeft | Qt::AlignVCenter);case Qt::DisplayRole:{if (nColumn == FILE_NAME_COLUMN){return record.strFileName;}else if (nColumn == DATE_TIME_COLUMN){return record.dateTime;}else if (nColumn == FILE_SIZE_COLUMN){return record.nSize;}return "";}default:return QVariant();}return QVariant(); }// 表頭數據 QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const {switch (role){case Qt::TextAlignmentRole:return QVariant(Qt::AlignLeft | Qt::AlignVCenter);case Qt::DisplayRole:{if (orientation == Qt::Horizontal){if (section == FILE_NAME_COLUMN)return QStringLiteral("名稱");if (section == DATE_TIME_COLUMN)return QStringLiteral("修改日期");if (section == FILE_SIZE_COLUMN)return QStringLiteral("大小");}}default:return QVariant();}return QVariant(); }// 表格可選中 Qt::ItemFlags TableModel::flags(const QModelIndex &index) const {if (!index.isValid())return QAbstractItemModel::flags(index);Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;return flags; }接口說明
updateData
主要用于更新數據,刷新界面。data
用來顯示數據,根據角色(顏色、文本、對齊方式、選中狀態等)判斷需要顯示的內容。setData
用來設置數據,根據角色(顏色、文本、對齊方式、選中狀態等)判斷需要設置的內容。headerData
用來顯示水平/垂直表頭的數據。flags
用來設置單元格的標志(可用、可選中、可復選等)。
使用
QTableView *pTableView = new QTableView(this); TableModel *pModel = new TableModel(this); QSortFilterProxyModel *pProxyModel = new QSortFilterProxyModel(this); // 設置數據源模型 pProxyModel->setSourceModel(pModel); pTableView->setModel(pProxyModel); // 設置可排序 pTableView->setSortingEnabled(true); // 設置按照文件名升序排列 pTableView->sortByColumn(FILE_NAME_COLUMN, Qt::AscendingOrder);// 構造數據,更新界面 QList<FileRecord> recordList;// 獲取隨機值 QTime time = QTime::currentTime(); qsrand(time.msec() + time.second()*1000);for (int i = 0; i < 5; ++i) {int nIndex = qrand()%20 + 1;int nHour = qrand()%24;int nMinute = qrand()%60;int nSecond = qrand()%60;int nBytes = qrand()%100000;QDateTime dateTime(QDate(2016, 5, 1), QTime(nHour, nMinute, nSecond));FileRecord record;record.strFileName = QString("Name %1.cpp").arg(nIndex);record.dateTime = dateTime;record.nSize = nBytes;recordList.append(record); } pModel->updateData(recordList);思考
細心地童鞋可能會發現,當點擊表頭(文件名)的時候,如果按照升序排列時,順序依次是:Name 14、Name 19、Name 4、Name 8、Name 9,降序則相反。為什么呢?
其實這個很好理解,因為文件名所在的列顯示的數據類型為QString,而QString排序是按照第一個字母開始比較,直至最后一個字母,例如:Name 19和Name 4,首先比較Name是相同的,當比較1和4(注意這里不是按照整形比較19和4)的時候,發現1比4小,所以Name 19排在Name 4之前。
對于文件大小的顯示,一般情況下,我們顯示的是KB、MB、GB等單位,而不會顯示字節,那么按照1的說法,在這種情況下,升序排列時,10 K 就會排在8 K之前了,所以我們應該避免這種問題。
上面所述的簡單排序誰都會,如何把前面的數據按照字符串比較,而后面的數據按照整形比較呢?如何將整形顯示為字符串,而排序依然正常呢?這都是我們下節要分享的精彩內容,請持續關注!
轉載于:https://www.cnblogs.com/itrena/p/5938375.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Qt之QHeaderView排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu中root用户和user用户
- 下一篇: 【代码笔记】iOS-浮动的云