VS2010+QT5编程之QTableView数字排序

时间:2021-09-26 20:25:50

很多人发现QTableView中的排序很不科学,比如列排序的一列数101、35、2、87、5、779,排序出来变成了101、2、35、5、779、87。再比如“中国”、“山东”、“济南”、“历下”这一列字符串,排序出来会变成“中国”、“历下”、“山东”、“济南”。

先说一下QTableView如何设置排序,首先请不要设置水平标题头隐藏(行排序请不要设置垂直标题头隐藏),代码如下:

    QHeaderView *headers = tableview->horizontalHeader(); 
headers->setSortIndicator(0, Qt::AscendingOrder);
    headers->setSortIndicatorShown(true);
    headers->setSectionsClickable(true);

    connect(headers, SIGNAL(sectionClicked(int)), this->tableview, SLOT (sortByColumn(int))); 

 
再谈一下QTableView中的排序,其QT源码如下: 
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;  
    }  
}
总的来说,QTableView中的排序可以分为三种:int、float、double等这类的数字排序,Date、Time、DateTime这类的时间排序,String的字符串排序。出现数字排序不科学的原因应该是把数字作为字符串赋值,导致排序按字符串的方式排序。而中文字符串的排序是按照Unicode中文编码排序,据说是按照康熙字典的偏旁部首笔画排序,所以看起来很不科学。

那么怎么让数字排序科学起来呢?相信很多新手喜欢这样赋值:

QStandardItem *item = new QStandardItem("123");
其实这正是产生把数字以字符串的方式赋值的原因,正确的赋值方式如下:

QStandardItem *item = new QStandardItem;
int n = 123;
item->setData(QVariant(n),Qt::EditRole);
现在你会发现,数字的排序又变科学了。