QT自定義QTableView的排序方式
阿新 • • 發佈:2019-02-14
1、通常情況下,我們都是對QTableView的Item的text進行排序的(Qt::DisplayRole),實際上還可以對其他內容進行排序(參考enum Qt::ItemDataRole)
2、預設情況下,Item的排序是按照字串的方式來排序的,這就是為什麼我們看到排序結果類似於: ("100","20","3","400")。
3、通過追看QT(4.6.1)的原始碼,發現QTableView的排序函式sortByColumn根源在QAbstractItemModel,但其中的排序函式什麼都沒做,實際上還是在"QStandardItemModel::sort(int column, Qt::SortOrder order)"中實現的,排序函式有依賴於 "bool QStandardItem::operator<(const QStandardItem &other) const"。上面引號中內容都在"/qt-everywhere-opensource-src-4.6.1/src/gui/itemviewsqstandarditemmodel.cpp"中。 如下:
- /*!
- Returns true if this item is less than /a other; otherwise returns false.
- The default implementation uses the data for the item's sort role (see
- QStandardItemModel::sortRole) to perform the comparison if the item
- belongs to a model; otherwise, the data for the item's Qt::DisplayRole
- (text()) is used to perform the comparison.
- sortChildren() and QStandardItemModel::sort() use this function when
- sorting items. If you want custom sorting, you can subclass QStandardItem
- and reimplement this function.
- */
- bool QStandardItem::operator<(const QStandardItem &other) const
- {
- const int role = model() ? model()->sortRole() : Qt::DisplayRole;
- const QVariant l = data(role), r = other.data(role);
- // this code is copied from QSortFilterProxyModel::lessThan()
- switch (l.userType()) {
- case QVariant::Invalid:
- return (r.type() == QVariant::Invalid);
- case QVariant::Int:
- return l.toInt() < r.toInt();
- case QVariant::UInt:
- return l.toUInt() < r.toUInt();
- case QVariant::LongLong:
- return l.toLongLong() < r.toLongLong();
- case QVariant::ULongLong:
- return l.toULongLong() < r.toULongLong();
- case QMetaType::Float:
- return l.toFloat() < r.toFloat();
- case QVariant::Double:
- return l.toDouble() < r.toDouble();
- case QVariant::Char:
- return l.toChar() < r.toChar();
- case QVariant::Date:
- return l.toDate() < r.toDate();
- case QVariant::Time:
- return l.toTime() < r.toTime();
- case QVariant::DateTime:
- return l.toDateTime() < r.toDateTime();
- case QVariant::String:
- default:
- return l.toString().compare(r.toString()) < 0;
- }
- }
4、實際上我們要做的就是,繼承QStandardItem並重載operator<,下面是我的實現,根據需要還得過載拷貝建構函式和operator=。
- class QuoteItem: public QStandardItem
- {
- public:
- QuoteItem(){}
- QuoteItem(const QString &text)
- :QStandardItem(text)
- {
- }
- QuoteItem(const QuoteItem &other)
- : QStandardItem(other)
- {
- }
- QuoteItem &operator=(const QuoteItem &other)
- {
- QStandardItem::operator=(other);
- return *this;
- }
- virtual bool operator<(const QStandardItem &other) const
- {
- const QVariant l = data(Qt::DisplayRole), r = other.data(Qt::DisplayRole);
- if (column() == other.column() && other.column() >= 1 && other.column() <= 15)
- {
- return l.toDouble() < r.toDouble();
- }
- return QStandardItem::operator<(other);
- }
- };
我的目的是,讓第1列到第15列之間的item按照double的值大小來排序。
5、修改item時,使用下面的方式,還得稍作改變(dynamic_cast),可能還有更優雅的方式。
QuoteItem *oldItem = dynamic_cast<QuoteItem*>(model->item(row, column));