一、效果示例图
1.1 自定义表格排序示例图
本文过滤条件为行索引取余2等于0时返回true,且从下图中可以看到,奇偶行是各自挨在一起的。
1.2 自定义表格过滤示例图
下图添加两列条件(当前数据大于当前列条件才返回true,且多个列条件为且关系);下方添加条件分别为,”0列,条件值50“,”2列条件值40“,综合下来为0列值大于50且2列值大于40则返回true
二、相关理解
被动触发:不论是排序还是过滤,都会在添加数据的时候触发自定义排序/过滤函数;
主动触发:排序,可通过数据模型或过滤模型的sort函数触发;过滤,可通过setFilterRegExp函数触发。(此处说的两个函数主动调用后会运行自定义排序/过滤条件,前提是对应的函数有重写)
过滤:此外,除开本文写的filterAcceptsRow函数还有filterAcceptsColumn函数,其触发条件与filterAcceptsRow一致
三、源码
CMainWindow.h
#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H#include "CSortFilterProxyModel.h"#include <QMainWindow>
#include <QStandardItemModel>namespace Ui {
class CMainWindow;
}class CMainWindow : public QMainWindow
{Q_OBJECTpublic:explicit CMainWindow(QWidget *parent = nullptr);~CMainWindow();private slots:/*** @brief on_btnCustom_clicked 自定义条件添加响应函数*/void on_btnCustom_clicked();/*** @brief on_btnInitData_clicked 数据初始化响应函数*/void on_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;
}void CMainWindow::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("");
}void CMainWindow::on_btnInitData_clicked()
{// 虽然表格上是过滤模型,但是数据还是得设置到数据模型上才可for(int row = 0; row != 10; ++row){for(int col = 0; col != 10; ++col){// 设置当前行列的item, 并初始化随机值m_model->setItem(row, col, new QStandardItem(QString::number(rand() % 100)));}}
}
CMainWindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>CMainWindow</class><widget class="QMainWindow" name="CMainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>821</width><height>525</height></rect></property><property name="windowTitle"><string>CMainWindow</string></property><widget class="QWidget" name="centralWidget"><layout class="QGridLayout" name="gridLayout"><item row="2" column="1"><widget class="QLineEdit" name="editCondition"><property name="text"><string/></property><property name="placeholderText"><string>条件值</string></property></widget></item><item row="2" column="0"><widget class="QLineEdit" name="editCol"><property name="text"><string/></property><property name="placeholderText"><string>列</string></property></widget></item><item row="4" column="0" colspan="3"><widget class="QTableView" name="tableView"/></item><item row="1" column="0"><widget class="QPushButton" name="btnInitData"><property name="text"><string>初始化数据</string></property></widget></item><item row="1" column="1"><widget class="QPushButton" name="btnCustom"><property name="text"><string>添加自定义模型条件</string></property></widget></item></layout></widget><widget class="QMenuBar" name="menuBar"><property name="geometry"><rect><x>0</x><y>0</y><width>821</width><height>23</height></rect></property></widget><widget class="QToolBar" name="mainToolBar"><attribute name="toolBarArea"><enum>TopToolBarArea</enum></attribute><attribute name="toolBarBreak"><bool>false</bool></attribute></widget><widget class="QStatusBar" name="statusBar"/></widget><layoutdefault spacing="6" margin="11"/><resources/><connections/>
</ui>
CSortFilterProxyModel.h
#ifndef CSORTFILTERPROXYMODEL_H
#define CSORTFILTERPROXYMODEL_H#include <QSortFilterProxyModel>class CSortFilterProxyModel : public QSortFilterProxyModel
{Q_OBJECT
public:explicit CSortFilterProxyModel(QObject *parent = nullptr);/*** @brief appendCondition 追加条件函数* @param col 条件列* @param val 条件值*/void appendCondition(int col, int val);// QSortFilterProxyModel interface
protected:/*** @brief filterAcceptsRow 过滤行函数* @param source_row 当前行索引* @param source_parent 当前行父对象(没有则为空)* @return 过滤结果*/bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;/*** @brief lessThan 排序函数* @param source_left 比较的左值* @param source_right 比较的右值* @return 比较结果*/bool lessThan(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)
{}void CSortFilterProxyModel::appendCondition(int col, int val)
{// 直接赋值(不存在会添加,已存在会更新)m_mapFilterCondition[col] = val;
}bool CSortFilterProxyModel::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;
}bool CSortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{// 当前行为取余2等于0时返回true(就是说默认降序排序偶数行在前)return 0 == source_left.row() % 2;
}
总结
虽然自定义排序和过滤比较简单,但是在项目中非常实用,如需要将某行/列置顶,特殊条件过滤等。
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 o/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除