Qt之QHeaderView自定义排序(QSortFilterProxyModel)

简述

对以上节的排序,我们衍伸了两点:

  1. 把一个字符串前面的数据按照字符串比较,而后面的数据按照整形比较。
  2. 将整形显示为字符串,而排序依然正常呢。

为了分别描述,这里我们先解决问题1。

  • 简述
  • 效果
  • 处理大小显示
  • QAbstractTableModel
  • QSortFilterProxyModel
  • 提示

效果

处理大小显示

// 定义GB、MB、KB的计算常量
const int GB = 1024 * 1024 * 1024;
const int MB = 1024 * 1024;
const int KB = 1024;

QString bytesToGBMBKB(qint64 size)
{
    if (size / GB >= 1)
        return QString("%1 GB").arg(QString::number(size / (float)GB, 'f', 2));
    else if (size / MB >= 1)
        return QString("%1 MB").arg(QString::number(size / (float)MB, 'f', 2));
    else if (size / KB >= 1)
        return QString("%1 KB").arg(QString::number(size / (float)KB, 'f', 2));
    else
        return QString("%1 Bytes").arg(size);
}

QAbstractTableModel

这里只修改了一行代码,其它代码和上节相同。

// 表格项数据
QVariant TableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    int nRow = index.row();
    int nColumn = index.column();
    FileRecord record = m_recordList.at(nRow);

    switch (role)
    {
    case Qt::TextColorRole:
        return QColor(Qt::white);
    case Qt::TextAlignmentRole:
        return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
    case Qt::DisplayRole:
    {
        if (nColumn == FILE_NAME_COLUMN)
        {
            return record.strFileName;
        }
        else if (nColumn == DATE_TIME_COLUMN)
        {
            return record.dateTime;
        }
        else if (nColumn == FILE_SIZE_COLUMN)
        {
            // 之前返回的qint64,现在转换为字符串
            return bytesToGBMBKB(record.nSize);
        }

        return "";
    }
    default:
        return QVariant();
    }

    return QVariant();
}

QSortFilterProxyModel

QSortFilterProxyModel是用来排序和过滤的,不能单独使用,它只是一个“代理”,真正的数据需要QAbstractTableModel提供,可以重写lessThan来实现自己的排序算法。

SortFilterProxyModel::SortFilterProxyModel(QWidget *parent)
    : QSortFilterProxyModel(parent)
{

}

SortFilterProxyModel::~SortFilterProxyModel()
{

}

bool SortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
    if (!source_left.isValid() || !source_right.isValid())
        return false;

    if ((source_left.column() == FILE_NAME_COLUMN) && (source_right.column() == FILE_NAME_COLUMN))
    {
        QVariant leftData = sourceModel()->data(source_left);
        QVariant rightData = sourceModel()->data(source_right);

        if (leftData.canConvert<QString>() && rightData.canConvert<QString>())
        {
            QString strLeft = leftData.toString();
            QString strRight = rightData.toString();

            // 去掉后缀.cpp
            if (strLeft.contains("."))
            {
                int nIndex = strLeft.lastIndexOf(".");
                strLeft = strLeft.left(nIndex);
            }
            if (strRight.contains("."))
            {
                int nIndex = strRight.lastIndexOf(".");
                strRight = strRight.left(nIndex);
            }

            // 比较大小,如果字符串相同,则比较后面的整形数据
            QStringList strLeftList = strLeft.split(" ");
            QStringList strRightList = strRight.split(" ");
            if ((strLeftList.count() >= 2) && (strRightList.count() >= 2))
            {
                int nResult = QString::compare(strLeftList.at(0), strRightList.at(0), Qt::CaseInsensitive);
                if (nResult == 0)
                {
                    return strLeftList.at(1).toInt() < strRightList.at(1).toInt();
                }
                else
                {
                    return nResult;
                }
            }
        }
    }

    return QSortFilterProxyModel::lessThan(source_left, source_right);
}

提示

效果图中,只针对名称自定义排序了,大小只进行了转换,还尚未排序,因为存在多种解决方案,下节我会将方案一一列出,然后进行对比。

时间: 2024-08-03 00:16:25

Qt之QHeaderView自定义排序(QSortFilterProxyModel)的相关文章

Qt之QHeaderView自定义排序(终极版)

简述 本节主要解决自定义排序衍生的第二个问题-将整形显示为字符串,而排序依然正常. 下面我们介绍三种方案: 委托绘制 用户数据 辅助列 很多人也许会有疑虑,平时都用delegate来绘制各种按钮.图标.图形等操作,它还能排序?当然,它本身是不会排序的,但他的高级用法之一就是-辅助排序. 简述 委托绘制 效果 QStyledItemDelegate 眼见不一定为实 用户数据 QAbstractTableModel QSortFilterProxyModel 辅助列 效果 QAbstractTabl

Qt之QHeaderView自定义排序(获取正确的QModelIndex)

简述 前几节中分享过关于自定义排序的功能,貌似我们之前的内容已经可以很好地解决排序问题了,但是,会由此引发一些很难发现的问题...比如:获取QModelIndex索引错误. 下面,我们先来实现一个整行选中的效果. 简述 错误处理 效果 源码 分析 正常处理 效果 源码 错误处理 效果 下面是一个非正常的的效果,选中当前行会造成更新错误,Why? 源码 // 连接信号槽 connect(pTableView, SIGNAL(clicked(QModelIndex)), this, SLOT(onC

给WPS表格设置自定义排序

在使用wps处理数据的时候难免会遇到要使用排序的情况,而有些时候的排序又并不是单单的按照日期或者数字来排序,往往要根据实际的情况来进行排序工作,这使得的一些对排序功能不是特别了解的人来说无疑是一种痛苦,在这里我就教教大家怎么使用wps排序中的自定义排序哦首先呢我们举个栗子,以一个简单的表格为例 比如说我们希望以学历的高低来排序,那么我们首先要准备自定义的排序序列,以逗号隔开,要注意的是这里的逗号是英文输入法下的逗号哦,不要用中文输入法下的标点哦,把这个序列复制下来 然后我们要做的是点击wps左上

php 数组自定义排序:php二维数组自定义排序

<?php//对二维数组自定义排序function array_sort($arr,$keys,$type){$keysvalue=array();$i = 0;foreach($arr as $key=>$val) {$val[$keys] = str_replace("-","",$val[$keys]);$val[$keys] = str_replace(" ","",$val[$keys]);$val[$k

[开发故事]第三回,实现集合类Sort自定义排序

对集合元素进行排序是经常发生的事情,事实上大部分的集合类型都默认实现 了Sort方法,进行其元素的排序操作.例如List<T>集合的Sort方法有: public void Sort(); public void Sort(Comparison<T> comparison); public void Sort(IComparer<T> comparer); public void Sort(int index,int count,IComparer<T> c

自定义排序Excel数据的方法

  自定义排序Excel数据的方法         下面是一张按产品ID排序好了的表格,现在想要达到的目标是:将表格按照类别"海鲜,特制品,谷类/麦片,肉/家禽"序列依次排序. 1.选中要排序的表格中的某个单元格,切换到"数据"选项卡,在"排序和筛选"组中单击"排序"按钮. 2.在弹出的"排序"对话框中将主要关键字设置为"类别",然后单击"次序"下拉框右侧的按钮,选择

Excel表格中自定义排序序列的方法

   Excel表格中自定义排序序列的方法         1.启动Excel 2013并打开工作表,任意选取一个单元格后在"开始"选项卡的"编辑"组中单击"排序和筛选"按钮,在打开的下拉列表中选择"自定义排序"选项,如图1所示. 图1 选择"自定义排序"选项 2.打开"排序"对话框,在"次序"下拉列表中选择"自定义序列"选项,如图2所示. 图2

list泛型自定义排序示例

 这篇文章主要介绍了list泛型自定义排序示例,实现List泛型类将制定元素至前排序,大家参考使用吧 代码如下: static void Main(string[] args) {       Employee employee = new Employee();     //设置初始值     List<Employee> employeeList = new List<Employee>();     employeeList.Add(new Employee() { EmpI

Excel中自定义排序怎么使用

  Excel中自定义排序怎么使用?在工作中,有时我们需要在Excel中对数据进行快速排序,常用方法是选中要排序的区域,在菜单栏直接单击排序(升序或降序)即可;如果有时候这样操作不能满足你的需求,那么就需要自定义排序,具体方法如下: 步骤 打开Excel工作表,如图示: 选中要排序的区域. 打开自定义"排序"对话框. 操作过程如图. 说明:1.如果有多个条件,单击左上脚"添加条件".2.通过选项可以设置排序的方向和方法. 单击确定,得出如下结果. 以上就是在Exce