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);

为什么上面我用的是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);

还可以设置样式表等等,让表格更好看
在这里插入图片描述
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;  
    }  
}

可以看出排序可以分为三种: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;
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;
}

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

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

    case 10:
        columnContent = ScoreItem->biology + 10;
        break;

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

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值