文章目录
一、效果示例图
1.1 自定义表格排序示例图
本文过滤条件为行索引取余2等于0时返回true,且从下图中可以看到,奇偶行是各自挨在一起的。
1.2 自定义表格过滤示例图
下图添加两列条件(当前数据大于当前列条件才返回true,且多个列条件为且关系);下方添加条件分别为,”0列,条件值50“,”2列条件值40“,综合下来为0列值大于50且2列值大于40则返回true
二、相关理解
被动触发:不论是排序还是过滤,都会在添加数据的时候触发自定义排序/过滤函数;
主动触发:排序,可通过数据模型或过滤模型的sort函数触发;过滤,可通过setFilterRegExp函数触发。(此处说的两个函数主动调用后会运行自定义排序/过滤条件,前提是对应的函数有重写)
过滤:此外,除开本文写的filterAcceptsRow函数还有filterAcceptsColumn函数,其触发条件与filterAcceptsRow一致
三、源码
CMainWindow.h
#ifndefCMAINWINDOW_H#defineCMAINWINDOW_H#include"CSortFilterProxyModel.h"#include<QMainWindow>#include<QStandardItemModel>namespace Ui {classCMainWindow;}classCMainWindow:publicQMainWindow{
Q_OBJECT
public:explicitCMainWindow(QWidget *parent =nullptr);~CMainWindow();private slots:/**
* @brief on_btnCustom_clicked 自定义条件添加响应函数
*/voidon_btnCustom_clicked();/**
* @brief on_btnInitData_clicked 数据初始化响应函数
*/voidon_btnInitData_clicked();private:
Ui::CMainWindow *ui;
QStandardItemModel *m_model;// 数据模型
CSortFilterProxyModel *m_customFilterModel;// 自定义过滤器模型};#endif// CMAINWINDOW_H
CMainWindow.cpp
#include"CMainWindow.h"#include"ui_CMainWindow.h"#include<QMessageBox>CMainWindow::CMainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::CMainWindow){
ui->setupUi(this);// 数据模型对象创建
m_model =new QStandardItemModel;// 自定义过滤器类对象创建
m_customFilterModel =new CSortFilterProxyModel;// 设置数据源模型
m_customFilterModel->setSourceModel(m_model);// 先将正常数据模型类设置到表格中
ui->tableView->setModel(m_customFilterModel);// 设置表格可排序(设置过后通过自定义lessThan函数排序)
ui->tableView->setSortingEnabled(true);}CMainWindow::~CMainWindow(){// 释放内存空间delete m_customFilterModel;delete m_model;delete ui;}voidCMainWindow::on_btnCustom_clicked(){// 获取条件字符串
QString colStr = ui->editCol->text();
QString conditionStr = ui->editCondition->text();if(colStr.isEmpty()|| conditionStr.isEmpty()){QMessageBox::information(this,"提示","条件值为空,请输入条件");return;}// 获取条件并将其添加到自定义模型中
m_customFilterModel->appendCondition(ui->editCol->text().toInt(), ui->editCondition->text().toInt());// 条件列和条件值编辑框清空
ui->editCol->clear();
ui->editCondition->clear();// 通过设置过滤条件触发自定义过滤(此处条件不会影响自定义过滤)
m_customFilterModel->setFilterRegExp("");}voidCMainWindow::on_btnInitData_clicked(){// 虽然表格上是过滤模型,但是数据还是得设置到数据模型上才可for(int row =0; row !=10;++row){for(int col =0; col !=10;++col){// 设置当前行列的item, 并初始化随机值
m_model->setItem(row, col,newQStandardItem(QString::number(rand()%100)));}}}
CMainWindow.ui
<?xml version="1.0" encoding="UTF-8"?><uiversion="4.0"><class>CMainWindow</class><widgetclass="QMainWindow"name="CMainWindow"><propertyname="geometry"><rect><x>0</x><y>0</y><width>821</width><height>525</height></rect></property><propertyname="windowTitle"><string>CMainWindow</string></property><widgetclass="QWidget"name="centralWidget"><layoutclass="QGridLayout"name="gridLayout"><itemrow="2"column="1"><widgetclass="QLineEdit"name="editCondition"><propertyname="text"><string/></property><propertyname="placeholderText"><string>条件值</string></property></widget></item><itemrow="2"column="0"><widgetclass="QLineEdit"name="editCol"><propertyname="text"><string/></property><propertyname="placeholderText"><string>列</string></property></widget></item><itemrow="4"column="0"colspan="3"><widgetclass="QTableView"name="tableView"/></item><itemrow="1"column="0"><widgetclass="QPushButton"name="btnInitData"><propertyname="text"><string>初始化数据</string></property></widget></item><itemrow="1"column="1"><widgetclass="QPushButton"name="btnCustom"><propertyname="text"><string>添加自定义模型条件</string></property></widget></item></layout></widget><widgetclass="QMenuBar"name="menuBar"><propertyname="geometry"><rect><x>0</x><y>0</y><width>821</width><height>23</height></rect></property></widget><widgetclass="QToolBar"name="mainToolBar"><attributename="toolBarArea"><enum>TopToolBarArea</enum></attribute><attributename="toolBarBreak"><bool>false</bool></attribute></widget><widgetclass="QStatusBar"name="statusBar"/></widget><layoutdefaultspacing="6"margin="11"/><resources/><connections/></ui>
CSortFilterProxyModel.h
#ifndefCSORTFILTERPROXYMODEL_H#defineCSORTFILTERPROXYMODEL_H#include<QSortFilterProxyModel>classCSortFilterProxyModel:publicQSortFilterProxyModel{
Q_OBJECT
public:explicitCSortFilterProxyModel(QObject *parent =nullptr);/**
* @brief appendCondition 追加条件函数
* @param col 条件列
* @param val 条件值
*/voidappendCondition(int col,int val);// QSortFilterProxyModel interfaceprotected:/**
* @brief filterAcceptsRow 过滤行函数
* @param source_row 当前行索引
* @param source_parent 当前行父对象(没有则为空)
* @return 过滤结果
*/boolfilterAcceptsRow(int source_row,const QModelIndex &source_parent)const;/**
* @brief lessThan 排序函数
* @param source_left 比较的左值
* @param source_right 比较的右值
* @return 比较结果
*/boollessThan(const QModelIndex &source_left,const QModelIndex &source_right)const;private:
QMap<int,int> m_mapFilterCondition;// 条件值保存容器<列, 条件值>};#endif// CSORTFILTERPROXYMODEL_H
CSortFilterProxyModel.cpp
#include"CSortFilterProxyModel.h"#include<QDebug>#include<QStandardItemModel>CSortFilterProxyModel::CSortFilterProxyModel(QObject *parent):QSortFilterProxyModel(parent){}voidCSortFilterProxyModel::appendCondition(int col,int val){// 直接赋值(不存在会添加,已存在会更新)
m_mapFilterCondition[col]= val;}boolCSortFilterProxyModel::filterAcceptsRow(int source_row,const QModelIndex &source_parent)const{// 定义返回值变量bool ret =true;// 获取数据源模型对象,并转换为需要的类型模板
QStandardItemModel *srcModel =dynamic_cast<QStandardItemModel *>(sourceModel());if(nullptr!= srcModel){foreach(int col, m_mapFilterCondition.keys()){// 获取当前的item对象
QStandardItem *item = srcModel->item(source_row, col);// 此时对应item不为空且整形值要小于条件值才显示if(nullptr!= item && m_mapFilterCondition[col]> item->text().toInt()){
ret =false;break;}}}return ret;}boolCSortFilterProxyModel::lessThan(const QModelIndex &source_left,const QModelIndex &source_right)const{// 当前行为取余2等于0时返回true(就是说默认降序排序偶数行在前)return0== source_left.row()%2;}
总结
虽然自定义排序和过滤比较简单,但是在项目中非常实用,如需要将某行/列置顶,特殊条件过滤等。
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 o/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除
版权归原作者 lw向北. 所有, 如有侵权,请联系我们删除。