当前位置: 首页 > news >正文

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&#xff0c;且从下图中可以看到&#xff0c;奇偶行是各自挨在一起的。 1.2 自定义表格过滤示例图 下图添加两列条件&#xff08;当前数据大于当前列条件才返回true&#xff0c;且多个列…...

电商(强一致性系统)的场景设计

领域拆分&#xff1a;如何合理地拆分系统&#xff1f; 一般来说&#xff0c;强一致性的系统都会牵扯到“锁争抢”等技术点&#xff0c;有较大的性能瓶颈&#xff0c;而电商时常做秒杀活动&#xff0c;这对系统的要求更高。业内在对电商系统做改造时&#xff0c;通常会从三个方面…...

算法与数据结构(一)

一、时间复杂度 一个操作如果和样本的数据量没有关系&#xff0c;每次都是固定时间内完成的操作&#xff0c;叫做常数操作。 时间复杂度为一个算法流程中&#xff0c;常数操作数量的一个指标。常用O(读作big O)来表示。具体来说&#xff0c;这个算法流程中&#xff0c;发生了多…...

【Python】元组如何创建?

嗨害大家好鸭&#xff01;我是小熊猫~ Python 元组 Python 的元组与列表类似&#xff0c; 不同之处在于元组的元素不能修改。 元组使用小括号&#xff0c;列表使用方括号。 元组创建很简单&#xff0c;只需要在括号中添加元素&#xff0c; 并使用逗号隔开即可。 如下实例…...

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个数字只有一个&#xff0c;其他数字都有两个。找出这两个数字。a, b 用HashMap记录就不说了。 这里记录一下用异或的方式解决。 由于异或特性为自己异或自己为0。a^a 0;所以可以异或数组中的所有数字得出 a^b 的结果&#xff0c;其他相同的都消掉…...

python支持的操作系统有哪些

支持python开发环境的系统有Linux、OSX和windows&#xff0c;以及所有主要的操作系统中。 Linux&#xff0c;Linux系统是为编程而设计的&#xff0c;因此在大多数Linux计算机中&#xff0c;都默认安装了Python。编写和维护Linux的人认为会使用这种系统进行编程。要在Linux中运…...

S3C2440开发环境搭建

拿出了之前的S3C2440开发板&#xff0c;然后把移植uboot、移植内核、制作根文件系统、设备树编写驱动等几项再做一遍&#xff0c;这篇文章先记录下环境搭建过程&#xff0c;以及先把现成的uboot、内核、根文件系统下载进去&#xff0c;看看开发板还能不能用&#xff0c;先熟悉一…...

软件测试之测试用例

测试用例 1. 测试用例定义 测试用例又叫做test case&#xff0c;是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,以便测试某个程序路径或核实是否满足某个特定需求。 2. 编写测试用例的原因 2.1 理清思路&#xff0c;避免遗漏 如果测试的项目大而复杂&#…...

null和undefined的区别有哪些?

null和undefined的区别有哪些&#xff1f;相同点不同点undefinednull总结相同点 1.null和undefined都是js的基本数据类型 2.undefined和null都是假值&#xff08;falsy&#xff09;,都能作为条件进行判断&#xff0c;所以在绝大多数情况下两者在使用上没有区别 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的生命周期里&#xff0c;每个类只会被加载一次。 类加载的原则&#xf…...

ledcode【用队列实现栈】

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

【基础算法】双指针----字符串删减

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…...

Billu靶场黑盒盲打——思路和详解

一、信息收集 1、探测内网主机IP可以使用各种扫描工具比如nmap&#xff0c;我这里用的是自己编写的。 nmap -n 192.168.12.0/24 #扫描IP&#xff0c;发现目标主机 2、先不着急&#xff0c;先收集一波它的端口&#xff08;无果&#xff09; nmap -n 192.168.12.136 -p 1-10000…...

【2363. 合并相似的物品】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你两个二维整数数组 items1 和 items2 &#xff0c;表示两个物品集合。每个数组 items 有以下特质&#xff1a; items[i] [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 &#xff0c;we…...

【C++提高编程】C++全栈体系(二十四)

C提高编程 第三章 STL - 常用容器 九、map/ multimap容器 1. map基本概念 简介&#xff1a; map中所有元素都是pairpair中第一个元素为key&#xff08;键值&#xff09;&#xff0c;起到索引作用&#xff0c;第二个元素为value&#xff08;实值&#xff09;所有元素都会根…...

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】使…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

Redis:现代应用开发的高效内存数据存储利器

一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发&#xff0c;其初衷是为了满足他自己的一个项目需求&#xff0c;即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源&#xff0c;Redis凭借其简单易用、…...