QT教程:QSortFilterProxyModel代理实现自定义排序、联合过滤

news2024/11/24 4:40:29

1. QsortFilterProxyModel介绍

QsortFilterProxyModel类用来为model和view之间提供强大的排序和过滤支持。将模型排序或者过滤后在视图上显示,并且无需对模型中的数据进行任何转换,也无需对模型在中数据进行修改。

比如: 对某列筛选带有”xxx”的关键字出来.并支持多则表达式

使用代理的项视图模型代码如下:

QTreeView *treeView = new QTreeView;  
MyItemModel *sourceModel = new MyItemModel(this);
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(sourceModel); //将model放入代理中 
treeView->setModel(proxyModel); //在视图中安装代理

2.QSortFilterProxyModel自定义排序

自定义排序需要子类化QsortFilterProxyModel,然后重写lessThan().

注意 : 如果重写了lessThan(),那么就不会再调用model的sort方法了.

lessThan()使用示例:

bool SortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
    //通过当前视图中的index位置获取model中实际的数据
    QVariant leftData = sourceModel()->data(source_left);
    QVariant rightData = sourceModel()->data(source_right);
    switch ( source_left.column() )
    {
        case 0 :     //序号,需要判断数字
        case 3 :     //信号ID,需要判断数字
            return leftData.toInt() < rightData.toInt();
            break;
        default :    //其它,只判断字符串
            return leftData.toString() < rightData.toString();
            break;
    }
 
    return true;     
 
}

除了排序外,QSortFilterProxyModel还可以用来隐藏与某个过滤器不匹配的项。使用QRegExp对象指定筛选器,并将筛选器应用于给定列的每个项的filterRole() (默认情况下为Qt::DisplayRole)。QRegExp对象可用于匹配正则表达式、通配符模式或固定字符串。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

3.过滤方法1-使用setFilterKeyColumn()过滤列

首先需要通过void QsortFilterProxyModel::setFilterRegExp(const QRegExp &regExp)来设置FilterProxyModel的过滤器.

然后通过QsortFilterProxyModel::setFilterKeyColumn(int)来过滤某一列.

如果要更改大小写匹配,可以通过QsortFilterProxyModel::sortCaseSensitivity()来设置.

示例代码如下所示:

QTableView *view = new QTableView;   
MyItemModel *sourceModel = new MyItemModel(this);
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(sourceModel); //将model放入代理中   
view->setModel(proxyModel);             //在视图中安装代理

QRegExp regExp("^(-?\\d+)(\\.\\d+)?$", Qt::CaseSensitive, QRegExp::RegExp);
//通过^(-?\d+)(\.\d+)?$来匹配整数
proxyModel->setFilterRegExp(regExp);   //安装过滤器

proxyModel->setFilterKeyColumn(0);    
proxyModel->setFilterKeyColumn(2);    //将第一列和第三列同时是整数的数据显示出来.

每当过滤格式改变,则setFilterRegExp()重新更新过滤器即可.

弊端:

  • 但是这样只能"与方式"显示model,要第一列和第三列公共是整数的才能显示出来,不能实现"或方式"显示.

所以,如果要使用联合多列过滤,建议使用过滤方法2来实现.

4.过滤方法2-重写filterAcceptsRow成员函数

以实现"只要第一列有整数或者第三列有整数的都显示出来"为例,首先需要子类化QsortFilterProxyModel类,然后重写filterAcceptsRow()或者filterAcceptsColumn()函数.

由于我们筛选第一列和第三列,列号是明确的,而行号是未知的, 所以我们只重写filterAcceptsRow()函数.

示例代码如下所示:

bool SortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
    //获取model中实际的数据
    QString dataColumn1 =  sourceModel()->index(source_row, 0, source_parent).data(Qt::DisplayRole).toString();
    QString dataColumn3 =  sourceModel()->index(source_row, 2, source_parent).data(Qt::DisplayRole).toString();
    if(dataColumn1.contains(this->filterRegExp()))     
    {
        return true;
    }
    else if(dataColumn3.contains(this->filterRegExp())) 
    {
        return true;
    }
    return false;        
 
}

然后创建SortFilterProxyModel类时,只需要安装过滤器即可:

SortFilterProxyModel *proxyModel = new SortFilterProxyModel();
proxyModel->setSourceModel(sourceModel);            //将model放入代理中   
treeView->setModel(proxyModel);                     //在视图中安装代理
proxyModel->setFilterRegExp("^(-?\\d+)(\\.\\d+)?$"); //安装过滤器

每当过滤格式改变,则setFilterRegExp()重新更新过滤器即可.

注意事项:

  • 如果过滤方式改变了,比如从过滤第1列变成了过滤第2列,需要调用invalidateFilter()函数,使之前的过滤失效,激活当前过滤.

5.代码示例

model采用上章代码的CustomModel为例.支持筛选多列、筛选模式支持:或方式、与方式、

界面实现如下所示:

#ifndef SORTFILTERPROXYMODEL_H
#define SORTFILTERPROXYMODEL_H

#include <QObject>
#include <QSortFilterProxyModel>
#include <QList>

class SortFilterProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT

    virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
    virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
    bool m_isOr;
    QList<int> m_selectdList;

public:
    explicit SortFilterProxyModel(QSortFilterProxyModel *parent = nullptr);

    void ChangeFilterMode(bool isOr);        
    void ChangeFilterColumn( QList<int> selectdList);         

signals:

};

#endif // SORTFILTERPROXYMODEL_H

sortfilterproxymodel.cpp如下所示:

#include "sortfilterproxymodel.h"
#include <QDebug>
SortFilterProxyModel::SortFilterProxyModel(QSortFilterProxyModel *parent)
    : QSortFilterProxyModel(parent)
{

}


void SortFilterProxyModel::ChangeFilterMode(bool isOr)    
{
    m_isOr = isOr;
    invalidateFilter();
}
void SortFilterProxyModel::ChangeFilterColumn( QList<int> selectdList)     
{
    m_selectdList = selectdList;
    invalidateFilter();
}


bool SortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{

    if(m_selectdList.isEmpty())
        return true;

    foreach(int column, m_selectdList) {

         QString data =  sourceModel()->index(source_row, column, source_parent).data(Qt::DisplayRole).toString();

         bool mathd = this->filterRegularExpression().match(data).hasMatch();


         if(m_isOr && mathd) {    
           return true;
         } else if(!m_isOr && !mathd) {     
             return false;
         }

    }

    if(m_isOr)          
        return false;
    else
        return true;
}

bool SortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
    //通过当前视图中的index位置获取model中实际的数据
    QVariant leftData = sourceModel()->data(source_left);
    QVariant rightData = sourceModel()->data(source_right);

    switch ( source_left.column() )
    {
        case 0 :  
        case 3 :   
            return leftData.toInt() < rightData.toInt();
            break;
        default :    
            return leftData.toString() < rightData.toString();
            break;
    }


    return true;

}

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/43386.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maya——1——在maya中,用Arnold(阿诺德)还原Subtance Painter(sp)中的材质效果。

1根据上图的导出选项&#xff0c;在sp中设置arnold的导出参数&#xff0c;得到五张贴图&#xff0c;删掉其中的高度图&#xff08;用不上&#xff09;留下这四张 base&#xff08;基础颜色&#xff09; Metallic&#xff08;金属度&#xff09; Normal&#xff08;法线&#x…

Google Colab训练yolov3自定义数据集

共分7步&#xff1a; 一、进入Google Colab训练环境 二、下载编译Darknet 三、上传数据集 四、修改配置文件 五、下载预训练权重文件 六、开始训练数据 七、测试训练结果 一、进入Google Colab训练环境 打开 Google Drive 云端硬盘 新建Google Colaboratory文件&#xff0c;…

公共大数据集群中如何配置 YARN 的公平调度器和容量调度器

公共大数据集群中如何配置 YARN 的公平调度器和容量调度器 1 YARN 资源管理框架与公平/容量调度器 作为一款资源调度框架&#xff0c;Yarn 支持可插拔的调度器&#xff0c;常见的调度器有公平调度器 fair scheduler 和容量调度器 capacity scheduler。常见的大数据发行版中&a…

一张照片,如何生成一个二维码?

冬天落在恭王府的第一场大雪、春天聚在河边觅食的麻雀、盛夏午后从冰箱里拿出来的大西瓜、深秋爬满南墙的红叶……每一份惊喜和快乐&#xff0c;都值得分享给更多的朋友。 今天我们要介绍的是&#xff0c;如何将一张照片&#xff0c;做成一个二维码&#xff0c;扫码后就可以看…

利用两个小demo理解汇编代码排查内存溢出问题

利用两个小demo理解汇编代码排查内存溢出问题 https://www.cnblogs.com/liuchuanloong/articles/16925695.html 【背景】 近日处理现场问题时遇到了踩内存导致的崩溃问题&#xff0c;然而个人对反汇编程序执行过程不熟悉&#xff0c;通过查阅资料&#xff0c;对比分析两个小d…

不适用于云的应用程序有哪些?

所有应用程序都适合在云上运行吗?这是在云计算中寻求改进IT解决方案的企业经常问的一个问题。这个问题的答案是“视情况而定”。虽然企业云的应用正在飞速发展&#xff0c;大多数企业都在考虑将整个应用程序迁移到云上&#xff0c;以实现可伸缩、灵活、可访问、敏捷和精益的工…

PC端配置定位服务步骤(依赖于腾讯位置服务)

目录 第一步 &#xff1a; 安装 jsonp 第二步 &#xff1a; 在mian.js中配置并使用 第三步 &#xff1a; 在 manifest.json中进行相关配置 第四步 &#xff1a; 获取经纬度值&#xff0c;从而得到地址 第一步 &#xff1a; 安装 jsonp 执行此代码 &#xff1a; np…

Origin2022安装教程

Origin2022他来了&#xff01; 本人虽然是Python和R的资深绘图用户&#xff0c;偶尔也用用Origin&#xff0c;Origin的优势区间是手动、全可控&#xff0c;要素复杂事图片效果好&#xff1a; 安装方法和安装包下载破解见文末&#xff1a; Origin 2022新要素 1.对地理要素和…

基于 51 单片机室内灯光控制系统

1. 功能介绍 这是基于 STC89C52 单片机设计的灯光控制系统&#xff0c;实现对室内灯光的控制&#xff0c;采集光敏传感器&#xff0c;红外线热释电传感器&#xff0c;声音传感器&#xff0c;光照照度传感器等数据进行处理&#xff0c;完成室内灯光的智能控制。 支持的功能与设…

VBox组件内部局域网

我使用VirtualBox并不是很专业&#xff0c;只是拿它来组件服务器。后来这个虚拟机对我越来越重要&#xff0c;我的各种测试服务器和学习服务器越来越多&#xff0c;于是我就给他们规划了IP地址&#xff0c;像这样: 我用的网络一直都是桥接&#xff0c;每个虚拟机都可以上网&…

高性能HTTP和反向代理Web服务器 - Nginx

Nginx一、安装1.1.Windows安装1.2.Linux安装1.3.常用命令二、动静分离三、反向代理3.1.正向代理3.2.反向代理四、负载均衡4.1.轮询4.2.加权轮询4.3.Ip hash五、限流六、缓存七、黑白名单Nginx是一个高性能的HTTP服务器和反向代理的web服务器&#xff0c;同时也提供IMAP&#xf…

一文带你读懂公司卫生间一直有人窜稀的原理

不知道你有没有这样的经历&#xff0c;一直忙忙碌碌&#xff0c;需求不断&#xff0c;当你终于解决完手头的事情&#xff0c;突然特别着急想要去卫生间的时候&#xff0c;仅有的几个门总是关着的&#xff0c;于是怀疑&#xff0c;可能其他人更需要这次机会&#xff0c;他们也一…

华为云安装Docker,在其中安装Tomcat运行Html项目一步到位

一日不学习浑身难受&#xff0c;对于追光者的我来说&#xff0c;就是这种情况&#xff01;&#xff01;&#xff01;今天心血来潮&#xff0c;想把云服务器、Docker、Tomcat、Html项目集成一块进行练习&#xff0c;为了后面的部署项目做准备。 环境介绍&#xff1a;华为云cent…

KafKa存储机制

目录 存储机制 kafka 存储选型 Kafka 存储方案剖析 kafka 存储架构设计 kafka 日志系统架构设计 日志目录布局 磁盘数据存储 可靠性 Producer的可靠性保证 kafka 配置为 CP系统 kafka 配置为 AP系统 Broker 的可靠性保证 Consumer 的可靠性策略 AutoCommit&#xff…

【二叉树从无到有】

目录&#xff1a;前言一、树1.什么是树结构&#xff1f;2.为什么使用树结构&#xff1f;3.树的概念4.树的表示5.树在现实生活中的应用二、二叉树&#xff08;一&#xff09;二叉树概念既结构1.概念2.现实中的二叉树3.特殊的二叉树4.二叉树的性质5.二叉树的存储结构&#xff08;…

线程的深度剖析

线程和进程的区别和联系&#xff1a; 1.进程可以处理多并发编程的问题&#xff0c;但是进程太重&#xff0c;主要指它的资源分配和资源回收上&#xff0c;进程消耗资源多&#xff0c;速度慢&#xff0c;其创建、销毁、调度一个进程开销比较大。 2.线程的出现有效地解决了这一…

面向对象的个人理解(使用JAVA代码描述)

前言 功能分类 类&#xff08;class&#xff09;的第一个功能是隔离&#xff0c;起到边界的作用&#xff0c;使得不同功能的代码互不干扰。 干扰的起源 在非面向对象的语言中&#xff0c;我们主要定义结构和函数来实现功能。下边用C语言来举个例子。 某程序员写了宠物模拟…

Ajax学习:nodejs安装+express框架介绍

ajsx应用中&#xff0c;需要安装nodejs环境 基于Chrome V8引擎&#xff08;和浏览器上的谷歌的解析引擎一样&#xff09;JavaScript运行环境 (31条消息) Node.js_安装_哇嘎123的博客-CSDN博客 查看安装是否完成 express框架介绍--为了创建一个web服务器 (31条消息) Express…

Spark系列之Spark体系架构

title: Spark系列 第四章 Spark体系架构 4.1 Spark核心功能 Alluxio 原来叫 tachyon 分布式内存文件系统Spark Core提供Spark最基础的最核心的功能&#xff0c;主要包括&#xff1a; 1、SparkContext 通常而言&#xff0c;DriverApplication的执行与输出都是通过SparkC…

STM32G491RCT6,STM32H743BIT6规格书 32bit IC MCU

STM32G4系列将强大的ArmCortex-M4加上FPU和DSP能力与丰富和先进的模拟外设相结合。它引入了两种新的数学加速器(Cordic和Filtering)&#xff0c; CAN-FD (Flexible Datarate)&#xff0c;USB Type-C接口的功率传输&#xff0c;包括物理层(PHY)和先进的安全功能。&#xff08;图…