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"中。 如下:

[cpp:nogutter]  view plain copy
  1. /*! 
  2.     Returns true if this item is less than /a other; otherwise returns false. 
  3.  
  4.     The default implementation uses the data for the item's sort role (see 
  5.     QStandardItemModel::sortRole) to perform the comparison if the item 
  6.     belongs to a model; otherwise, the data for the item's Qt::DisplayRole 
  7.     (text()) is used to perform the comparison. 
  8.  
  9.     sortChildren() and QStandardItemModel::sort() use this function when 
  10.     sorting items. If you want custom sorting, you can subclass QStandardItem 
  11.     and reimplement this function. 
  12. */  
  13. bool QStandardItem::operator<(const QStandardItem &other) const  
  14. {  
  15.     const int role = model() ? model()->sortRole() : Qt::DisplayRole;  
  16.     const QVariant l = data(role), r = other.data(role);  
  17.     // this code is copied from QSortFilterProxyModel::lessThan()  
  18.     switch (l.userType()) {  
  19.     case QVariant::Invalid:  
  20.         return (r.type() == QVariant::Invalid);  
  21.     case QVariant::Int:  
  22.         return l.toInt() < r.toInt();  
  23.     case QVariant::UInt:  
  24.         return l.toUInt() < r.toUInt();  
  25.     case QVariant::LongLong:  
  26.         return l.toLongLong() < r.toLongLong();  
  27.     case QVariant::ULongLong:  
  28.         return l.toULongLong() < r.toULongLong();  
  29.     case QMetaType::Float:  
  30.         return l.toFloat() < r.toFloat();  
  31.     case QVariant::Double:  
  32.         return l.toDouble() < r.toDouble();  
  33.     case QVariant::Char:  
  34.         return l.toChar() < r.toChar();  
  35.     case QVariant::Date:  
  36.         return l.toDate() < r.toDate();  
  37.     case QVariant::Time:  
  38.         return l.toTime() < r.toTime();  
  39.     case QVariant::DateTime:  
  40.         return l.toDateTime() < r.toDateTime();  
  41.     case QVariant::String:  
  42.     default:  
  43.         return l.toString().compare(r.toString()) < 0;  
  44.     }  
  45. }  

4、实际上我们要做的就是,继承QStandardItem并重载operator<,下面是我的实现,根据需要还得重载拷贝构造函数和operator=。

[c-sharp:nogutter]  view plain copy
  1. class QuoteItem: public QStandardItem  
  2. {  
  3. public:  
  4.     QuoteItem(){}  
  5.   
  6.     QuoteItem(const QString &text)  
  7.         :QStandardItem(text)  
  8.     {  
  9.     }  
  10.   
  11.     QuoteItem(const QuoteItem &other)  
  12.         : QStandardItem(other)  
  13.     {  
  14.     }  
  15.   
  16.     QuoteItem &operator=(const QuoteItem &other)  
  17.     {  
  18.         QStandardItem::operator=(other);  
  19.         return *this;  
  20.     }  
  21.   
  22.   
  23.     virtual bool operator<(const QStandardItem &other) const  
  24.     {  
  25.         const QVariant l = data(Qt::DisplayRole), r = other.data(Qt::DisplayRole);  
  26.         if (column() == other.column()  && other.column() >= 1 && other.column() <= 15)  
  27.         {  
  28.             return l.toDouble() < r.toDouble();  
  29.         }  
  30.   
  31.         return QStandardItem::operator<(other);  
  32.     }  
  33. };  

我的目的是,让第1列到第15列之间的item按照double的值大小来排序。

5、修改item时,使用下面的方式,还得稍作改变(dynamic_cast),可能还有更美观的方式。

QuoteItem *oldItem = dynamic_cast(model->item(row, column)); 

你可能感兴趣的:(Qt)