本文属于《QTreeView使用系列教程》之一,欢迎查看其它文章。

一、QSortFilterProxyModel简介

QSortFilterProxyModel的使用比较简单,我们在上一章,使用它来实现排序时,已经大概使用过了。本章我们主要使用它实现对QTreeView中行列的筛选过滤。它是一个model代理类,需要配合原始数据model使用。

我们先来看看QSortFilterProxyModel的设置过滤器函数,如下:

void setFilterRegExp(const QRegExp &regExp);

参数QRegExp正则表达式类,其构造函数,包括pattern-匹配字符串,cs-匹配字符串是否区分大小写,syntax-使用的匹配语法(正则表达式、通配符、固定字符串等)。

enum PatternSyntax {RegExp,Wildcard,FixedString,RegExp2,WildcardUnix,W3CXmlSchema11 };QRegExp(const QString &pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive,PatternSyntax syntax = RegExp);

故,我们只需要将QRegExp对象通过setFilterRegExp设置到代理model,就可以实现对表项的匹配过滤了。怎么样,是不是比较简单。

二、使用QSortFilterProxyModel实现基本过滤

首先,我们在界面上放置QLineEdit和QComboBox,分别输入匹配字符串和匹配语法。QComboBox添加数据,并把PatternSyntax类型的正则表达式、通配符、固定字符串枚举值,与每个item关联,如下:

    ui->comboBox->addItem(tr("正则表达式"), QRegExp::RegExp);ui->comboBox->addItem(tr("通配符"), QRegExp::Wildcard);ui->comboBox->addItem(tr("固定字符串"), QRegExp::FixedString);

界面如下:

添加QLineEdit的textChanged信号处理

void MainWindow::on_lineEdit_textChanged(const QString &text)
{QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(ui->comboBox->currentData().toInt());QRegExp regExp(text, Qt::CaseInsensitive, syntax);proxyModel->setFilterRegExp(regExp);
}

然后将proxyModel添加到view,就ok了。

proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(model);
proxyModel->setFilterKeyColumn(0);
ui->treeView->setModel(proxyModel);

使用正则表达式,效果:

使用通配符,效果:

使用固定字符串,效果:

小贴士:

在QTreeView下,使用QSortFilterProxyModel进行过滤,会有一个问题,就是若父节点不符合过滤条件,则父节点以及子节点都不会显示。但是我们有时候需要实现若父节点不符合过滤条件,但是其子节点中有一个符合,那么走到这个子节点的所有父节点都需要显示出来,包括子节点自身也要显示出来。在QListView、QTableView中,因为没有父子层级关系,所以不存在这个问题。接下来,下面一节我们针对这个问题对QSortFilterProxyModel进行一点改造,来解决这个问题。

本章涉及工程代码:

文末,公众号回复:34FilterExample1,即可下载。

三、派生QSortFilterProxyModel实现行列过滤

为解决上面提到的问题,我们派生QSortFilterProxyModel,重写filterAcceptsRow,如下:

bool TreeFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
{bool filter = QSortFilterProxyModel::filterAcceptsRow(row, parent);if (filter) // 若本来此节点就允许显示,则直接返回true。{return true;}else // 若此节点不允许显示,则需要判断此节点下面子节点是否有满足过滤条件的,若有,则需要显示此节点。{QModelIndex source_index = sourceModel()->index(row, 0, parent);for (int i = 0; i < sourceModel()->rowCount(source_index); i++){if (filterAcceptsRow(i, source_index)){return true;}}}return false;
}

上面讲解的都是对行进行过滤,而每列都是全部显示出来的,所以在本节,我们再扩展下,实现对列的过滤。我们重写filterAcceptsColumn,实现只显示column_s至column_e之间的列,如下:

bool TreeFilterProxyModel::filterAcceptsColumn(int column, const QModelIndex &parent) const
{if (column_s == 0 && column_e == 0)return QSortFilterProxyModel::filterAcceptsColumn(column, parent);if (column < column_s || column > column_e)return false;return true;
}

然后将proxyModel添加到view。

proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(model);
ui->treeView->setModel(proxyModel);

然后,我们需要添加一些界面控件和处理信号槽,界面如下:

添加QLineEdit的textChanged信号处理执行过滤。

void MainWindow::on_lineEdit_textChanged(const QString &text)
{QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(ui->comboBox->currentData().toInt());QRegExp regExp(text, Qt::CaseInsensitive, syntax);proxyModel->setFilterRegExp(regExp);
}

添加在第几列匹配过滤器,处理函数。setFilterKeyColumn参数,index表示列号,-1表示对所有列匹配;默认值为0,只对第0列匹配。

void MainWindow::on_comboBox_2_currentIndexChanged(int index)
{if (index == 8)proxyModel->setFilterKeyColumn(-1);elseproxyModel->setFilterKeyColumn(index);
}

允许显示的列功能区,添加2个QSpinBox处理函数。此处设置显示一个连续区间的列,可能不是很合理,一般第一列是肯定要显示,然后可以选择性显示其他某些列,可以不连续,此处只是简单演示一下。

void MainWindow::on_spinBox_valueChanged(int arg1)
{int begin = ui->spinBox->value();int end = ui->spinBox_2->value();proxyModel->setVisibleColumn(begin, end);on_lineEdit_textChanged(ui->lineEdit->text());
}void MainWindow::on_spinBox_2_valueChanged(int arg1)
{on_spinBox_valueChanged(0);
}

实现父节点不符合过滤条件,但子节点符合,此时父节点也要显示,效果如下:

实现列过滤,效果如下:

实现在第1列匹配过滤器,效果如下:

实现在所有列匹配过滤器,效果如下:

本章涉及工程代码:

文末,公众号回复:34FilterExample2,即可下载。


若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

《使用QSortFilterProxyModel实现QTreeView行列过滤》:系列教程之十相关推荐

  1. 推荐系统系列教程之十:协同过滤中的相似度计算方法有哪些?

    编者按:之前推出了<推荐系统系列教程>,反响不错,前面已经推出了九期,今天按约推出第十期:协同过滤中的相似度计量方法有哪些?希望朋友们多点"在看",多多转发,我会在&q ...

  2. SAP系统和微信集成的系列教程之十:如何在SAP C4C系统里直接回复消息给微信用户

    本系列的英文版Jerry写作于2017年,这个教程总共包含十篇文章,发表在SAP社区上. 系列目录 (1) 微信开发环境的搭建 (2) 如何通过微信公众号消费API (3) 微信用户关注公众号之后,自 ...

  3. sap系统搭建教程_SAP系统和微信集成的系列教程之十:如何在SAP C4C系统里直接回复消息给微信用户...

    本系列的英文版Jerry写作于2017年,这个教程总共包含十篇文章,发表在SAP社区上: https://blogs.sap.com/2017/12/10/wechat-development-ser ...

  4. java jdbc 教程_java JDBC系列教程之JDBC类的简析与JDBC的基础操作

    什么是JDBC? 概念:JAVA Database Connectivity Javas数据库连接,Java语言操作数据库接口,然后由各个数据库厂商去实现这个接口,提供数据库驱动java包,我们可以使 ...

  5. 乐鑫代理-启明云端分享ESP32系列教程之二:Linux搭建esp-idf环境

    提示:此教程依据乐鑫官方的ESP32入门教程总结而来,仅供个人参考学学习,如有错误,欢迎批评指正.乐鑫官方参考: 乐鑫官方文档地址 1.搭建esp-idf环境 1.1安装虚拟机与Ubuntu 未安装请 ...

  6. 10 51单片机汇编:让定时器产生中断(使用Keil模拟器)[系列教程之10]

    10 51单片机汇编:让定时器产生中断(使用Keil模拟器)[系列教程之10] 该系列主仓库地址:https://gitee.com/langcai1943/8051-from-boot-to-app ...

  7. 一步一步实现STM32-FOTA系列教程之FLASH静态区读写

    一步一步实现STM32-FOTA系列教程之FLASH静态区读写 文章系列链接 <一步一步实现STM32-FOTA系列教程之bin文件生成> <一步一步实现STM32-FOTA系列教程 ...

  8. 一步一步实现STM32-FOTA系列教程之Bootloader编写

    一步一步实现STM32-FOTA系列教程之Bootloader编写 文章系列链接 <一步一步实现STM32-FOTA系列教程之bin文件生成> <一步一步实现STM32-FOTA系列 ...

  9. MSP430FR6989系列教程之LCD

    MSP430FR6989系列教程之LCD 由于MSP430以追求低功耗的特性,所以在MSP430FR6989上搭载的LCD并不是我们通常意义上的LCD显示屏(TFT LCD),而是段式 LCD MSP ...

最新文章

  1. Linux/docker下oracle开启监听,开启自动启动
  2. 关于多态override/overload
  3. [JSP][JSTL]页面调用函数--它${fn:}内置函数、是推断字符串是空的、更换车厢
  4. 逆向学习技术!拆解驱动器,学习布局走线技术
  5. SCSI、FC、iSCSI三大协议概述
  6. spring mvc学习(34):restful的delete
  7. pointcut 切面表达式 切入点表达式
  8. 刚刚!频域通道注意力网络FcaNet开源了!
  9. JVM快速调优手册v1.0之三:内存分配策略
  10. 从零实现深度学习框架——自动求导神器计算图
  11. Java 条形码 二维码 的生成与解析
  12. 72. 文件上传(1)
  13. java 编译单个文件_单独Java文件的通用快速编译方法
  14. HTML5七夕情人节表白网页制作【流星动画3D相册】HTML+CSS+JavaScript
  15. 【明解C语言】之函数详解《上篇》
  16. activiti选择上一步下一步处理人
  17. 不忘初心,砥砺前行。
  18. 手机百度云如何打开doc
  19. 做程序员久了,你会不会感觉的空虚与迷茫?其实主要原因是这几点!
  20. 苹果Mac电脑中如何将键盘当作鼠标使用?

热门文章

  1. Linux操作与管理文件(多次打开同一文件,文件共享,fcntl函数,标准IO库)
  2. 去除网站讨厌的 javaScript 脚本
  3. 通达信交易系统接口是不是免费的?
  4. 三星android 5.0升级名单,三星可升级Android 7系统机型名单曝光
  5. O365 Manager Plus详解
  6. 89c51电话按键c语言代码,基于AT89C51单片机电话拨号系统设计.docx
  7. 嘉兴桐乡技能培训-平面设计入门看过来
  8. 第四话-开放封闭原则
  9. tomcat是什么?通俗解释
  10. 【LiteOS】LiteOS移植常见问题分析