• QTableView对自定义的Model排序


    QTableView对自定义的Model排序

    1.先看图实例来理解

    QTableView,翻译过来就是表格视图,表格视图中有表头,行列等基础属性,QTableView的典型界面,如下图所示
    在这里插入图片描述
    我用工作的实例给大家演示,更形象
    在这里插入图片描述在这里插入图片描述以上都是排序好的QTableView的效果,里面的所有数据都是自定义的Model,从数据库中获取的

    2.问题来了,怎么实现排序的呢

    我这里自定义的Model是继承自QAbstractTableModel的实现的,在这里要说一下,要想把QTableView等视图玩的花,秀,就得自己写model
    我用一个在工作中简单点的自定义model演示,如下,想让整个表格按第三列的领出时间,按时间先后进行排序,如下图是没有排序的效果,默认是按第一列的名称进行排序,不是我们想要的效果
    在这里插入图片描述
    我的model表头信息如下
    在这里插入图片描述
    这里的model信息都是从数据库中筛选获取的
    在这里插入图片描述
    获取到数据model之后,要将model显示在QTableView上,要想实现我们的效果,就得把获取到的model设置为排序模型,如下:

    // 设置表格数据模型,增加排序模型
    QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(m_model.data());
    tableView->setModel(proxyModel);
    
    • 1
    • 2
    • 3
    • 4

    为什么上面我用的是m_model.data()呢,因为我的m_model是共享指针,要转化为普通指针,就要调用方法.data()
    在这里插入图片描述
    最后一步,QTableView设置排序即可

        //生成一个排序、筛选模型,实现排序功能或者筛选的模型
        QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
        //设置源数据模型
        proxyModel->setSourceModel(m_model.data());
    
        //设置proxyModel模型
        m_TableView->setModel(proxyModel);
        //设置允许点击表头进行排序
        m_TableView->setSortingEnabled(true);
        //初始化某一列的排序,升序或者降序
        m_TableView->sortByColumn(4, Qt::SortOrder::AscendingOrder);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    还可以设置样式表等等,让表格更好看
    在这里插入图片描述
    QTableView对自定义的Model排序这样子就实现了

    效果如下:

    在这里插入图片描述
    也可以通过点击表头对应的列,进行顺序排序

    应用场景

    QTableView的应用场景可就多了,它是不是很像.xlsx表格
    在这里插入图片描述
    所以他可以通过一定的方法,转化为xlsx,导出来
    应用场景还有,我们电脑的文件系统的显示
    在这里插入图片描述
    补充: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;  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    可以看出排序可以分为三种:int、float、double等这类的整形,浮点型排序,Date、Time、DateTime这类的时间,日期排序,char、String的字符/串排序
    所以我们传值的时候,要注意类型的传递,假如你想要实现数字的排序,不能将数字转化字符串传入,这样你排序时就按字符串排了,因为传入的是QVariant型的,你传入的时候,要按照严格的类型传入,才能实现想要的排序
    如下:我写了一个学生成绩表,存储在sqlite数据库里
    在这里插入图片描述

    我要将数据拿出来,就要有一个学生成绩类,里面的每一个字段对应着数据库中每个地段的类型
    在这里插入图片描述
    在数据库将数据查询完后,将数据转化为学生成绩类的相应字段
    在这里插入图片描述
    获取完数据库的所有数据后,返回,在由YC_Score型转化为QObjetct*
    在这里插入图片描述
    然后重置自定义的model数据
    将model数据放入排序模型中
    然后将排序模型设置为m_TableView(视图)的模型,就是要看到的视图
    在这里插入图片描述
    这种必须要重写model中的data方法,这个决定了我们在视图中每一列要显示信息,在这里控制

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    
    • 1
    ScoreModel::ScoreModel(QObject *parent):BaseTableModel(parent)
    {
        //                      0      1       2      3      4       5      6      7       8     9     10
        QStringList header = {"学号", "姓名", "年龄", "语文", "数学", "历史", "政治", "地理", "化学","物理","生物"};
        setHeader(header);
    }
    
    QVariant ScoreModel::data(const QModelIndex &index, int role) const
    {
        if(!index.isValid())
        {
            return QVariant();
        }
    
        if (role == Qt::TextAlignmentRole)
        {
            return Qt::AlignCenter;
        }
    
        if (role != Qt::DisplayRole)
        {
            return QVariant();
        }
    
        int row = index.row();
    
        if (!(row < rowCount()))
        {
            return QVariant();
        }
    
        YC_Score *ScoreItem = dynamic_cast<YC_Score *>(getObject(row));
    
        if (ScoreItem == nullptr)
        {
            return QVariant();
        }
    
        int column = index.column();
        QVariant columnContent;
        switch (column)
        {
        case 0:
            columnContent = ScoreItem->ID;
            break;
        case 1:
            columnContent = ScoreItem->name;
            break;
        case 2:
            columnContent = ScoreItem->age;
            break;
        case 3:
            columnContent = ScoreItem->chinese;
            break;
        case 4:
            columnContent = ScoreItem->math;
            break;
        case 5:
            columnContent = ScoreItem->history;
            break;
        case 6:
            columnContent = ScoreItem->politics;
            break;
        case 7:
            columnContent = ScoreItem->geography;
            break;
        case 8:
            columnContent = ScoreItem->chemistry;
            break;
        case 9:
            columnContent = ScoreItem->physics;
            break;
        case 10:
            columnContent = ScoreItem->biology;
            break;
        default:
            break;
        }
        return columnContent;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    我们要显示的表格一共有十列,这里直接将内容返回即可。不要统一转化为统一的类型在返回,因为返回值是QVariant型的,你想怎么排序,你就返回什么类型进行填充即可。这样才能在后续的点击表头排序时,根据每一列的类型进行相适应的排序。

    如我们想要最后一个科目生物分数都加十分,直接在第一个返回的这里+10即可。如下,这就是MVC数据模型视图分离的精髓,将他们分离开,保证数据间的独立性,修改模型,转化为视图显示给我们看,不影响数据。

        case 10:
            columnContent = ScoreItem->biology + 10;
            break;
    
    • 1
    • 2
    • 3

    这样子就可以啦
    在这里插入图片描述
    要排序,点击一下表头相应的字段,即可顺逆序排序
    在这里插入图片描述
    好了,补充那么多在这里插入图片描述

  • 相关阅读:
    【吐血整理】年度盘点 2019年Java面试题汇总篇——附答案
    Vue学习笔记四
    python对英雄皮肤进行图片采集~
    UEFI FD 文件分析
    Java 8 中需要知道的4个函数式接口-Function、Consumer、Supplier、Predicate
    中职网络安全技能大赛SSH弱口令渗透测试解析
    学不会PDF裁剪与PDF拆分?6个方法包你轻松学会
    怎么改变placeholder提示字的颜色用CSS
    【408专项篇】C语言笔记-第七章(函数)
    第04章_运算符
  • 原文地址:https://blog.csdn.net/qq_44667165/article/details/126583696