目录

  • 引言
  • 实现方式
  • 完整代码

引言

Qt界面开发中经常用到Model/View视图模型框架,通常一个Model对应多个View进行显示,节省刷新资源消耗。Model在使用是经常需要进行过滤或是排序,如果重新创建Model显然不是一个明智的选择,可以使用QSortFilterProxyModel完成过滤及排序,代理只是调整了两个数据集索引的映射关系,不是原Model的拷贝,增删改原数据会在代理上显现,同时节约了资源开销。

实现方式

过滤可通过重写QSortFilterProxyModel的filterAcceptsRow函数实现。原本的过滤只有一级节点,没有遍历子节点判断是否满足条件,修改如下:

bool SortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{if(filterRegExp().isEmpty()==false){QModelIndex source_index = sourceModel()->index(source_row, this->filterKeyColumn(), source_parent) ;if(source_index.isValid()){// 遍历子节点,如果子节点符合过滤条件同样显示for(int i=0; i<sourceModel()->rowCount(source_index); ++i){if(filterAcceptsRow(i, source_index))return true ;}return filterIndexByCustom(source_index);}}// parent call for initial behaviourreturn QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent) ;
}

而排序重写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);// 颠倒顺序return leftData.toString() > rightData.toString();
}

完整代码

Demo效果如下:

#include <QMainWindow>
#include <QDialog>
#include <QSortFilterProxyModel>
#include <QStringListModel>
#include <QListView>
#include <QComboBox>
#include <QLineEdit>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QTreeView>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass SortFilterProxyModel;
class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void slot_reapplyFilter();private slots:void on_addBtn_clicked();void on_delBtn_clicked();void on_pushButton_clicked();private:Ui::MainWindow *ui;private:QStandardItemModel* m_sourceModel;SortFilterProxyModel *m_proxyModel;SortFilterProxyModel *m_checkModel;
};class SortFilterProxyModel : public QSortFilterProxyModel
{Q_OBJECTpublic:SortFilterProxyModel(QObject *parent = nullptr);virtual ~SortFilterProxyModel();private:virtual bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const;virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;protected:virtual bool filterIndexByCustom(const QModelIndex & source_index) const;
};
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->patternCombox->addItem("RegExp",QRegExp::RegExp);ui->patternCombox->addItem("Wildcard",QRegExp::Wildcard);ui->patternCombox->addItem("Fixed string",QRegExp::FixedString);m_sourceModel = new QStandardItemModel(this);foreach(QString str, QColor::colorNames()){auto tmpItem = new QStandardItem(str);//tmpItem->setCheckable(true);for (int i=0; i<3; i++) {tmpItem->appendRow(new QStandardItem(QString::number(i)));//tmpItem->child(i)->setCheckable(true);for (int j=0; j<2; j++) {tmpItem->child(i)->appendRow(new QStandardItem(QString::number(j + 100)));}}m_sourceModel->appendRow(tmpItem);}m_proxyModel = new SortFilterProxyModel(this);m_proxyModel->setSourceModel(m_sourceModel);// 设置源模型m_proxyModel->setFilterKeyColumn(0);// 设置应用过滤的列m_proxyModel->setFilterRole(Qt::DisplayRole);m_proxyModel->setSortRole(Qt::DisplayRole);m_checkModel = new SortFilterProxyModel(this);m_checkModel->setSourceModel(m_sourceModel);ui->sourceView->setModel(m_sourceModel);ui->proxyView->setModel(m_proxyModel);connect(ui->filterEdit, &QLineEdit::textChanged, this, &MainWindow::slot_reapplyFilter);connect(ui->patternCombox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MainWindow::slot_reapplyFilter);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::slot_reapplyFilter()
{QRegExp::PatternSyntax syntax = (QRegExp::PatternSyntax)ui->patternCombox->currentData().toInt();QRegExp regExp(ui->filterEdit->text(),Qt::CaseInsensitive,syntax);m_proxyModel->setFilterRegExp(regExp);
}void MainWindow::on_addBtn_clicked()
{QString itemName = ui->itemEidt->text().trimmed();if(!itemName.isEmpty()){m_sourceModel->appendRow(new QStandardItem(itemName));}
}void MainWindow::on_delBtn_clicked()
{QModelIndex currentIndex = ui->sourceView->currentIndex();if(currentIndex.isValid()){m_sourceModel->removeRow(currentIndex.row());}
}void MainWindow::on_pushButton_clicked()
{m_proxyModel->sort(0);
}SortFilterProxyModel::SortFilterProxyModel(QObject *parent): QSortFilterProxyModel(parent)
{}SortFilterProxyModel::~SortFilterProxyModel()
{}bool SortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{if(filterRegExp().isEmpty()==false){QModelIndex source_index = sourceModel()->index(source_row, this->filterKeyColumn(), source_parent) ;if(source_index.isValid()){// 遍历子节点for(int i=0; i<sourceModel()->rowCount(source_index); ++i){if(filterAcceptsRow(i, source_index))return true ;}// 遍历父节点//QModelIndex parentIndex = source_parent;//while (parentIndex.isValid()) {//    if(filterIndexByCustom(parentIndex))//        return true;//    parentIndex = parentIndex.parent();//}return filterIndexByCustom(source_index);}}// parent call for initial behaviourreturn QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent) ;
}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);// 颠倒顺序return leftData.toString() > rightData.toString();
}bool SortFilterProxyModel::filterIndexByCustom(const QModelIndex &source_index) const
{QString key = sourceModel()->data(source_index, filterRole()).toString();return key.contains(filterRegExp()) ;
}

QSortFilterProxyModel的使用相关推荐

  1. 【Qt中文手册】QSortFilterProxyModel

    1.说明 QSortFilterProxyModel类继承自QAbstractProxyModel是一个代理类,存在于另一模型Model和视图View之间,将另一个模型排序或者过滤后在视图上显示. 2 ...

  2. QT的QSortFilterProxyModel类的使用

    详细说明 QSortFilterProxyModel类支持对在另一个模型和视图之间传递的数据进行排序和过滤. QSortFilterProxyModel可以用于对项目进行排序,过滤项目或同时对两者进行 ...

  3. Qt工作笔记-自定义QSortFilterProxyModel实现多列分别过滤

    程序运行截图如下: 原理,重写QSortFilterProxyModel类中的filterAcceptsRow即可: 源码如下: mysortfilterproxymodel.h #ifndef MY ...

  4. 《使用QSortFilterProxyModel实现QTreeView行列过滤》:系列教程之十

    本文属于<QTreeView使用系列教程>之一,欢迎查看其它文章. 一.QSortFilterProxyModel简介 QSortFilterProxyModel的使用比较简单,我们在上一 ...

  5. QT重写QSortFilterProxyModel实现多列数据过滤

    在QTableView中可以使用QSortFilterProxyModel来过滤model的数据,可以通过setFilterKeyColumn(int colnum)设置需要过滤的列,当设置为-1时则 ...

  6. QSortFilterProxyModel实现排序、过滤

    1. QSortFilterProxyModel介绍 QSortFilterProxyModel类用来为model和view之间提供强大的排序和过滤支持.将模型排序或者过滤后在视图上显示,并且无需对模 ...

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

    1. QsortFilterProxyModel介绍 QsortFilterProxyModel类用来为model和view之间提供强大的排序和过滤支持.将模型排序或者过滤后在视图上显示,并且无需对模 ...

  8. QSortFilterProxyModel实现筛选与排序固定行号(垂直表头序号)

    上一篇我们讲述了数据更新相关: (43条消息) QAbstractTableModel使用详解&数据单条更新&整体更新_恭德的博客-CSDN博客https://blog.csdn.ne ...

  9. python表格控件_python GUI库图形界面开发之PyQt5表格控件QTableView详细使用方法与实例...

    PyQt5表格控件QTableView简介 在通常情况下,一个应用需要和一批数据进行交互,然后以表格的形式输出这些信息,这时就需要用到QTableView类了,在QTableView中可以使用自定义的 ...

最新文章

  1. 技术类人员的职业发展的4大方向
  2. SAP ABAP实用技巧介绍系列之 ABAP XSLT 定义变量
  3. 跨语言调用Hangfire定时作业服务
  4. python的pandas库中如何计算每列出现最多的值_Python Pandas:计算多个列的每个唯一值的显示次数...
  5. 全连接层的作用是什么?
  6. 终于解决了无运行无网上邻居的问题
  7. centos7下使用rpm包安装clickhouse
  8. 《Spring揭秘》知识点总结
  9. 简单脱壳教程笔记(6)---手脱FSG壳
  10. Netron简单使用教程
  11. 获取素材列表返回40004 invalid media type.获取公众号素材mediaId
  12. html+css制作月亮
  13. Unity Hub和Unity项目的关系
  14. Hadoop修改slaves的主机名,所要修改的文件
  15. 数据库(Mysql)----mysql建表中的约束
  16. 09驾校科目一考试系统——提交分数
  17. HDU5155 Harry And Magic Box
  18. xbox360链接pc_如何将PC游戏从Windows 10免费流式传输到Xbox One
  19. 基于Spark GraphX 的图形数据分析
  20. SEM是什么,基础知识讲解

热门文章

  1. 洛谷2762 太空飞行计划问题
  2. unity 一些有用的碎片知识整理 之 二 (之 四 持续更新中...)
  3. 【Windows畸形目录】畸形目录总结
  4. Android Studio下载安装
  5. Google “登陆”火星
  6. AI生成假指纹以假乱真,你的指纹识别还安全吗?
  7. B站兄弟连Linux学习——Linux系统简介
  8. Typora+colordrop+PicGo+GitHub图床,让Markdown飞(一)
  9. 如何在iPhone或iPad上裁剪和更改视频的长宽比
  10. xilinx DMA IP核(一) —— loop测试 代码注释