Qt利用QSortFilterProxyModel代理实现自定义排序与联合过滤

 更新时间:2022年11月29日 09:34:09   作者:音视频开发老舅  
QsortFilterProxyModel类用来为model和view之间提供强大的排序和过滤支持。这篇文章将利用QSortFilterProxyModel代理实现自定义排序与联合过滤,需要的可以参考一下

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对象可用于匹配正则表达式、通配符模式或固定字符串。

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利用QSortFilterProxyModel代理实现自定义排序与联合过滤的文章就介绍到这了,更多相关Qt QSortFilterProxyModel内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于curses库实现弹球游戏

    基于curses库实现弹球游戏

    这篇文章主要为大家详细介绍了基于curses库实现弹球游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • Qt无边框窗口拖拽和阴影的实现

    Qt无边框窗口拖拽和阴影的实现

    自定义窗口控件的无边框,窗口事件由于没有系统自带边框,无法实现拖拽拉伸等事件的处理,本文主要介绍了Qt无边框窗口拖拽和阴影的实现,感兴趣的可以了解一下
    2024-01-01
  • C++ 中的异常抛出和捕获方式

    C++ 中的异常抛出和捕获方式

    这篇文章主要介绍了C++ 中的异常抛出和捕获方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • C++头文件algorithm中的函数功能详解

    C++头文件algorithm中的函数功能详解

    这篇文章主要介绍了C++头文件algorithm中的函数功能详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • 深入解析C++中派生类的构造函数

    深入解析C++中派生类的构造函数

    这篇文章主要介绍了深入解析C++中派生类的构造函数,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++重载运算符实现分数加减乘除

    C++重载运算符实现分数加减乘除

    这篇文章主要为大家详细介绍了C++重载运算符实现分数加减乘除,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • C语言项目全正整数后再计算的三种参考解答方法

    C语言项目全正整数后再计算的三种参考解答方法

    今天小编就为大家分享一篇关于C语言项目全正整数后再计算的三种参考解答方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • C语言项目爬楼梯的两种实现方法参考

    C语言项目爬楼梯的两种实现方法参考

    今天小编就为大家分享一篇关于C语言项目爬楼梯的两种实现方法参考,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • C语言实现猜数字小游戏的示例代码

    C语言实现猜数字小游戏的示例代码

    猜数字小游戏是我们小时候喜欢我们一个经典小游戏。本文将用C语言实现这一经典游戏,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-08-08
  • C++ OpenCV学习之图像像素值统计

    C++ OpenCV学习之图像像素值统计

    在图像分析的时候,我们经常需要对单通道图像的像素进行统计。本文将主要介绍利用C++ OpenCV实现的图像像素值统计的几种方法,需要的可以参考一下
    2022-01-01

最新评论