1. 程式人生 > >QT自定義QTableView的排序方式

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

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

4、實際上我們要做的就是,繼承QStandardItem並重載operator<,下面是我的實現,根據需要還得過載拷貝建構函式和operator=。

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

我的目的是,讓第1列到第15列之間的item按照double的值大小來排序。

5、修改item時,使用下面的方式,還得稍作改變(dynamic_cast),可能還有更優雅的方式。

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