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


    1. QsortFilterProxyModel介绍

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

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

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

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

    2.QSortFilterProxyModel自定义排序

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

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

    lessThan()使用示例:

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

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

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

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

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

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

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

    示例代码如下所示:

    1. QTableView *view = new QTableView;
    2. MyItemModel *sourceModel = new MyItemModel(this);
    3. QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
    4. proxyModel->setSourceModel(sourceModel); //将model放入代理中
    5. view->setModel(proxyModel); //在视图中安装代理
    6. QRegExp regExp("^(-?\\d+)(\\.\\d+)?$", Qt::CaseSensitive, QRegExp::RegExp);
    7. //通过^(-?\d+)(\.\d+)?$来匹配整数
    8. proxyModel->setFilterRegExp(regExp); //安装过滤器
    9. proxyModel->setFilterKeyColumn(0);
    10. proxyModel->setFilterKeyColumn(2); //将第一列和第三列同时是整数的数据显示出来.

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

    弊端:

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

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

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

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

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

    示例代码如下所示:

    1. bool SortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
    2. {
    3. //获取model中实际的数据
    4. QString dataColumn1 = sourceModel()->index(source_row, 0, source_parent).data(Qt::DisplayRole).toString();
    5. QString dataColumn3 = sourceModel()->index(source_row, 2, source_parent).data(Qt::DisplayRole).toString();
    6. if(dataColumn1.contains(this->filterRegExp()))
    7. {
    8. return true;
    9. }
    10. else if(dataColumn3.contains(this->filterRegExp()))
    11. {
    12. return true;
    13. }
    14. return false;
    15. }

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

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

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

    注意事项:

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

    5.代码示例

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

    界面实现如下所示:

    1. #ifndef SORTFILTERPROXYMODEL_H
    2. #define SORTFILTERPROXYMODEL_H
    3. #include
    4. #include
    5. #include
    6. class SortFilterProxyModel : public QSortFilterProxyModel
    7. {
    8. Q_OBJECT
    9. virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
    10. virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
    11. bool m_isOr;
    12. QList<int> m_selectdList;
    13. public:
    14. explicit SortFilterProxyModel(QSortFilterProxyModel *parent = nullptr);
    15. void ChangeFilterMode(bool isOr);
    16. void ChangeFilterColumn( QList<int> selectdList);
    17. signals:
    18. };
    19. #endif // SORTFILTERPROXYMODEL_H

    sortfilterproxymodel.cpp如下所示:

    1. #include "sortfilterproxymodel.h"
    2. #include <QDebug>
    3. SortFilterProxyModel::SortFilterProxyModel(QSortFilterProxyModel *parent)
    4. : QSortFilterProxyModel(parent)
    5. {
    6. }
    7. void SortFilterProxyModel::ChangeFilterMode(bool isOr)
    8. {
    9. m_isOr = isOr;
    10. invalidateFilter();
    11. }
    12. void SortFilterProxyModel::ChangeFilterColumn( QList<int> selectdList)
    13. {
    14. m_selectdList = selectdList;
    15. invalidateFilter();
    16. }
    17. bool SortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
    18. {
    19. if(m_selectdList.isEmpty())
    20. return true;
    21. foreach(int column, m_selectdList) {
    22. QString data = sourceModel()->index(source_row, column, source_parent).data(Qt::DisplayRole).toString();
    23. bool mathd = this->filterRegularExpression().match(data).hasMatch();
    24. if(m_isOr && mathd) {
    25. return true;
    26. } else if(!m_isOr && !mathd) {
    27. return false;
    28. }
    29. }
    30. if(m_isOr)
    31. return false;
    32. else
    33. return true;
    34. }
    35. bool SortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
    36. {
    37. //通过当前视图中的index位置获取model中实际的数据
    38. QVariant leftData = sourceModel()->data(source_left);
    39. QVariant rightData = sourceModel()->data(source_right);
    40. switch ( source_left.column() )
    41. {
    42. case 0 :
    43. case 3 :
    44. return leftData.toInt() < rightData.toInt();
    45. break;
    46. default :
    47. return leftData.toString() < rightData.toString();
    48. break;
    49. }
    50. return true;
    51. }

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

  • 相关阅读:
    Linux三剑客之awk命令详解
    常见集群算法解析
    N-Gram模型介绍
    AI大模型技术:原理、应用和未来展望
    Django(8):请求对象和响应对象
    【来点小剧场--项目测试报告】个人博客项目自动化测试
    Spring5架构,万字文章带你学习
    基于 Glibc 版本升级的 DolphinDB 数据查询性能优化实践
    maven-resources-production:trunk-auth: java.lang.NegativeArraySizeException
    基于物联网的教室人数检测系统-设计说明书
  • 原文地址:https://blog.csdn.net/m0_60259116/article/details/128087948