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));