Qt之QTableView自定义排序/过滤(QSortFilterProxyModel实现,含源码+注释)
一、效果示例图
1.1 自定义表格排序示例图
本文过滤条件为行索引取余2等于0时返回true,且从下图中可以看到,奇偶行是各自挨在一起的。
1.2 自定义表格过滤示例图
下图添加两列条件(当前数据大于当前列条件才返回true,且多个列条件为且关系);下方添加条件分别为,”0列,条件值50“,”2列条件值40“,综合下来为0列值大于50且2列值大于40则返回true
二、相关理解
被动触发:不论是排序还是过滤,都会在添加数据的时候触发自定义排序/过滤函数;
主动触发:排序,可通过数据模型或过滤模型的sort函数触发;过滤,可通过setFilterRegExp函数触发。(此处说的两个函数主动调用后会运行自定义排序/过滤条件,前提是对应的函数有重写)
过滤:此外,除开本文写的filterAcceptsRow函数还有filterAcceptsColumn函数,其触发条件与filterAcceptsRow一致
三、源码
CMainWindow.h
#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H#include "CSortFilterProxyModel.h"#include <QMainWindow>
#include <QStandardItemModel>namespace Ui {
class CMainWindow;
}class CMainWindow : public QMainWindow
{Q_OBJECTpublic:explicit CMainWindow(QWidget *parent = nullptr);~CMainWindow();private slots:/*** @brief on_btnCustom_clicked 自定义条件添加响应函数*/void on_btnCustom_clicked();/*** @brief on_btnInitData_clicked 数据初始化响应函数*/void on_btnInitData_clicked();private:Ui::CMainWindow *ui;QStandardItemModel *m_model; // 数据模型CSortFilterProxyModel *m_customFilterModel; // 自定义过滤器模型
};#endif // CMAINWINDOW_H
CMainWindow.cpp
#include "CMainWindow.h"
#include "ui_CMainWindow.h"#include <QMessageBox>CMainWindow::CMainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::CMainWindow)
{ui->setupUi(this);// 数据模型对象创建m_model = new QStandardItemModel;// 自定义过滤器类对象创建m_customFilterModel = new CSortFilterProxyModel;// 设置数据源模型m_customFilterModel->setSourceModel(m_model);// 先将正常数据模型类设置到表格中ui->tableView->setModel(m_customFilterModel);// 设置表格可排序(设置过后通过自定义lessThan函数排序)ui->tableView->setSortingEnabled(true);
}CMainWindow::~CMainWindow()
{// 释放内存空间delete m_customFilterModel;delete m_model;delete ui;
}void CMainWindow::on_btnCustom_clicked()
{// 获取条件字符串QString colStr = ui->editCol->text();QString conditionStr = ui->editCondition->text();if(colStr.isEmpty() || conditionStr.isEmpty()){QMessageBox::information(this, "提示", "条件值为空,请输入条件");return;}// 获取条件并将其添加到自定义模型中m_customFilterModel->appendCondition(ui->editCol->text().toInt(), ui->editCondition->text().toInt());// 条件列和条件值编辑框清空ui->editCol->clear();ui->editCondition->clear();// 通过设置过滤条件触发自定义过滤(此处条件不会影响自定义过滤)m_customFilterModel->setFilterRegExp("");
}void CMainWindow::on_btnInitData_clicked()
{// 虽然表格上是过滤模型,但是数据还是得设置到数据模型上才可for(int row = 0; row != 10; ++row){for(int col = 0; col != 10; ++col){// 设置当前行列的item, 并初始化随机值m_model->setItem(row, col, new QStandardItem(QString::number(rand() % 100)));}}
}
CMainWindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>CMainWindow</class><widget class="QMainWindow" name="CMainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>821</width><height>525</height></rect></property><property name="windowTitle"><string>CMainWindow</string></property><widget class="QWidget" name="centralWidget"><layout class="QGridLayout" name="gridLayout"><item row="2" column="1"><widget class="QLineEdit" name="editCondition"><property name="text"><string/></property><property name="placeholderText"><string>条件值</string></property></widget></item><item row="2" column="0"><widget class="QLineEdit" name="editCol"><property name="text"><string/></property><property name="placeholderText"><string>列</string></property></widget></item><item row="4" column="0" colspan="3"><widget class="QTableView" name="tableView"/></item><item row="1" column="0"><widget class="QPushButton" name="btnInitData"><property name="text"><string>初始化数据</string></property></widget></item><item row="1" column="1"><widget class="QPushButton" name="btnCustom"><property name="text"><string>添加自定义模型条件</string></property></widget></item></layout></widget><widget class="QMenuBar" name="menuBar"><property name="geometry"><rect><x>0</x><y>0</y><width>821</width><height>23</height></rect></property></widget><widget class="QToolBar" name="mainToolBar"><attribute name="toolBarArea"><enum>TopToolBarArea</enum></attribute><attribute name="toolBarBreak"><bool>false</bool></attribute></widget><widget class="QStatusBar" name="statusBar"/></widget><layoutdefault spacing="6" margin="11"/><resources/><connections/>
</ui>
CSortFilterProxyModel.h
#ifndef CSORTFILTERPROXYMODEL_H
#define CSORTFILTERPROXYMODEL_H#include <QSortFilterProxyModel>class CSortFilterProxyModel : public QSortFilterProxyModel
{Q_OBJECT
public:explicit CSortFilterProxyModel(QObject *parent = nullptr);/*** @brief appendCondition 追加条件函数* @param col 条件列* @param val 条件值*/void appendCondition(int col, int val);// QSortFilterProxyModel interface
protected:/*** @brief filterAcceptsRow 过滤行函数* @param source_row 当前行索引* @param source_parent 当前行父对象(没有则为空)* @return 过滤结果*/bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;/*** @brief lessThan 排序函数* @param source_left 比较的左值* @param source_right 比较的右值* @return 比较结果*/bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;private:QMap<int, int> m_mapFilterCondition; // 条件值保存容器<列, 条件值>};#endif // CSORTFILTERPROXYMODEL_H
CSortFilterProxyModel.cpp
#include "CSortFilterProxyModel.h"#include <QDebug>
#include <QStandardItemModel>CSortFilterProxyModel::CSortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
{}void CSortFilterProxyModel::appendCondition(int col, int val)
{// 直接赋值(不存在会添加,已存在会更新)m_mapFilterCondition[col] = val;
}bool CSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{// 定义返回值变量bool ret = true;// 获取数据源模型对象,并转换为需要的类型模板QStandardItemModel *srcModel = dynamic_cast<QStandardItemModel *>(sourceModel());if(nullptr != srcModel){foreach(int col, m_mapFilterCondition.keys()){// 获取当前的item对象QStandardItem *item = srcModel->item(source_row, col);// 此时对应item不为空且整形值要小于条件值才显示if(nullptr != item && m_mapFilterCondition[col] > item->text().toInt()){ret = false;break;}}}return ret;
}bool CSortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{// 当前行为取余2等于0时返回true(就是说默认降序排序偶数行在前)return 0 == source_left.row() % 2;
}
总结
虽然自定义排序和过滤比较简单,但是在项目中非常实用,如需要将某行/列置顶,特殊条件过滤等。
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 o/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除
相关文章:

Qt之QTableView自定义排序/过滤(QSortFilterProxyModel实现,含源码+注释)
一、效果示例图 1.1 自定义表格排序示例图 本文过滤条件为行索引取余2等于0时返回true,且从下图中可以看到,奇偶行是各自挨在一起的。 1.2 自定义表格过滤示例图 下图添加两列条件(当前数据大于当前列条件才返回true,且多个列…...

电商(强一致性系统)的场景设计
领域拆分:如何合理地拆分系统? 一般来说,强一致性的系统都会牵扯到“锁争抢”等技术点,有较大的性能瓶颈,而电商时常做秒杀活动,这对系统的要求更高。业内在对电商系统做改造时,通常会从三个方面…...
算法与数据结构(一)
一、时间复杂度 一个操作如果和样本的数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。 时间复杂度为一个算法流程中,常数操作数量的一个指标。常用O(读作big O)来表示。具体来说,这个算法流程中,发生了多…...

【Python】元组如何创建?
嗨害大家好鸭!我是小熊猫~ Python 元组 Python 的元组与列表类似, 不同之处在于元组的元素不能修改。 元组使用小括号,列表使用方括号。 元组创建很简单,只需要在括号中添加元素, 并使用逗号隔开即可。 如下实例…...
qt操作文件以及字符串转换
//从文件加载英文属性与中文属性对照表QFile file(":/propertyname.txt");if (file.open(QFile::ReadOnly)) {//QTextStream方法读取速度至少快百分之30#if 0while(!file.atEnd()) {QString line file.readLine();appendName(line);}#elseQTextStream in(&file)…...
数组中只出现一次的两个数字(异或法思路)
题目简介 一个数组中只有2个数字只有一个,其他数字都有两个。找出这两个数字。a, b 用HashMap记录就不说了。 这里记录一下用异或的方式解决。 由于异或特性为自己异或自己为0。a^a 0;所以可以异或数组中的所有数字得出 a^b 的结果,其他相同的都消掉…...
python支持的操作系统有哪些
支持python开发环境的系统有Linux、OSX和windows,以及所有主要的操作系统中。 Linux,Linux系统是为编程而设计的,因此在大多数Linux计算机中,都默认安装了Python。编写和维护Linux的人认为会使用这种系统进行编程。要在Linux中运…...

S3C2440开发环境搭建
拿出了之前的S3C2440开发板,然后把移植uboot、移植内核、制作根文件系统、设备树编写驱动等几项再做一遍,这篇文章先记录下环境搭建过程,以及先把现成的uboot、内核、根文件系统下载进去,看看开发板还能不能用,先熟悉一…...
软件测试之测试用例
测试用例 1. 测试用例定义 测试用例又叫做test case,是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,以便测试某个程序路径或核实是否满足某个特定需求。 2. 编写测试用例的原因 2.1 理清思路,避免遗漏 如果测试的项目大而复杂&#…...
null和undefined的区别有哪些?
null和undefined的区别有哪些?相同点不同点undefinednull总结相同点 1.null和undefined都是js的基本数据类型 2.undefined和null都是假值(falsy),都能作为条件进行判断,所以在绝大多数情况下两者在使用上没有区别 if(undefined)…...

【强烈建议收藏:计算机网络面试专题:HTTP协议、HTTP请求报文和响应报文、HTTP请求报文常用字段、HTTP请求方法、HTTP响应码】
一.知识回顾 之前我们一起学习了HTTP1.0、HTTP1.1、HTTP2.0协议之前的区别、以及URL地址栏中输入网址到页面展示的全过程&&DNS域名解析的过程、HTTP协议基本概念以及通信过程、HTTPS基本概念、SSL加密原理、通信过程、中间人攻击问题、HTTP协议和HTTPS协议区别。接下来…...

关于Java中的静态块讲解
文章目录类的加载特性与时机类加载的特性类加载的时机static的三个常用地方什么是静态块?特点写法静态块 static怎么用?类的加载特性与时机 在介绍static之前可以先看看类的相关 类加载的特性 在JVM的生命周期里,每个类只会被加载一次。 类加载的原则…...

ledcode【用队列实现栈】
目录 题目描述: 解析题目 代码解析 1.封装一个队列 1.2封装带两个队列的结构体 1.3封装指向队列的结构体 1.4入栈函数实现 1.5出栈函数实现 1.6取栈顶数据 1.7判空函数实现 题目描述: 解析题目 这个题我是用c语言写的,所以队列的pu…...

【基础算法】双指针----字符串删减
🌹作者:云小逸 📝个人主页:云小逸的主页 📝Github:云小逸的Github 🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前…...

Billu靶场黑盒盲打——思路和详解
一、信息收集 1、探测内网主机IP可以使用各种扫描工具比如nmap,我这里用的是自己编写的。 nmap -n 192.168.12.0/24 #扫描IP,发现目标主机 2、先不着急,先收集一波它的端口(无果) nmap -n 192.168.12.136 -p 1-10000…...
【2363. 合并相似的物品】
来源:力扣(LeetCode) 描述: 给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数组 items 有以下特质: items[i] [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 ,we…...
【C++提高编程】C++全栈体系(二十四)
C提高编程 第三章 STL - 常用容器 九、map/ multimap容器 1. map基本概念 简介: map中所有元素都是pairpair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)所有元素都会根…...

c++11 标准模板(STL)(std::unordered_set)(十一)
定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…...

AI/CV大厂笔试LeetCode高频考题之基础核心知识点
AI/CV互联网大厂笔试LeetCode高频考题之基础核心知识点算法复习1、二叉树的遍历2、回溯算法3、二分搜索4、滑动窗口算法题5、经典动态规划6、动态规划答疑篇6.1、总结一下如何找到动态规划的状态转移关系7、编辑距离8、戳气球问题9、最长公共子序列 Longest Common Subsequence…...

华为OD机试题,用 Java 解【静态扫描最优成本】问题
最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
Django RBAC项目后端实战 - 03 DRF权限控制实现
项目背景 在上一篇文章中,我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统,为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...

【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理:检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目:RankRAG:Unifying Context Ranking…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)
注:文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件:STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...
当下AI智能硬件方案浅谈
背景: 现在大模型出来以后,打破了常规的机械式的对话,人机对话变得更聪明一点。 对话用到的技术主要是实时音视频,简称为RTC。下游硬件厂商一般都不会去自己开发音视频技术,开发自己的大模型。商用方案多见为字节、百…...