• 61.QT-QSortFilterProxyModel代理实现自定义排序、联合过滤


    在之前60.QT-QabstractTableModel模型、重写sort方法排序章节中,学习了如何用model,本章再来学习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为例.支持筛选多列、筛选模式支持:或方式、与方式、

    界面实现如下所示:

     下载链接:https://download.csdn.net/download/qq_37997682/13709981

     sortfilterproxymodel.h如下所示:

    #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;
    
    }
  • 相关阅读:
    CCPC-Wannafly Winter Camp Day8 (Div2, onsite)
    Codeforces gym101612 E.Equal Numbers(贪心)
    Codeforces gym101612 L.Little Difference(枚举+二分)
    Linq-ToList与ToArray
    SQL SERVER性能分析
    无法访问IIS 没有足够的特权访问计算机
    SQL SERVER获得指定表的主键
    SQL Server 中master..spt_values的应用
    买了阿里云之后:挂载新硬盘
    支付宝WAP支付接口开发
  • 原文地址:https://www.cnblogs.com/lifexy/p/14145629.html
Copyright © 2020-2023  润新知