QT自定义QTableView的排序方式

 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(model->item(row, column));  

你可能感兴趣的:(Qt,qt,sorting,function,less,string)