用自定义的QSortFilterProxyModel实现条件过滤,使qtableview中只显示满足条件的行信息

在实际开发中,qtableview是qt客户端页面中最常用的控件之一。运用qtableview的同时,也会存在着先对初始数据进行过滤,然后在qtableview上展示的只有满足条件的那些信息。或者在不同的条件下要展示出不同的满足条件的行信息。
第一种方法,就是我们在将数据设置在qtableview的model之前,将满足条件的信息筛选出来,然后直接填入model.
第二种方法,就是先不对数据进行处理,直接将数据塞入qtableview的model,然后再给qtableview设置一个筛选代理proxymodel(QSortFilterProxyModel)对model中数据进行刷选,然后展示出来的就是能满足条件的model.
1、先看项目目录结构

在这里插入图片描述

2、添加数据model文件, studentmodel.h,studentmodel.cpp
studentmodel.h



#include <QAbstractItemModel>
class Student
{
public:
    QString name;  //姓名
    int age;       //年龄
    int height;    //身高
    int weight;    //体重
};
Q_DECLARE_METATYPE(Student);

class StudentModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    enum {
        column_name = 0,
        column_age,
        column_height,
        column_weight
    };
    explicit StudentModel(QObject *parent = nullptr);

    void setInfo(QList<Student>& studentList);

    void clear();

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;

    QModelIndex parent(const QModelIndex &index) const override;

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

    int columnCount(const QModelIndex &parent = QModelIndex()) const override;

    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

private:
    QList<Student> m_studentList;

};
studentmodel.cpp


#include "studentmodel.h"

StudentModel::StudentModel(QObject *parent)
    : QAbstractItemModel{parent}
{

}

void StudentModel::setInfo(QList<Student>& studentList)
{
    m_studentList = studentList;
    beginInsertRows(QModelIndex(), 0, m_studentList.size() -1);
    endInsertRows();
}

void StudentModel::clear()
{
    m_studentList.clear();
    beginResetModel();
    endResetModel();
}

QModelIndex StudentModel::index(int row, int column, const QModelIndex &parent) const
{
    return createIndex(row, column, nullptr);
}

QModelIndex StudentModel::parent(const QModelIndex &index) const
{
    return QModelIndex();
}

int StudentModel::rowCount(const QModelIndex &parent) const
{
    return m_studentList.size();
}

int StudentModel::columnCount(const QModelIndex &parent) const
{
    return 4;
}

QVariant StudentModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Vertical)
    {
        return QVariant();
    }
    if (role == Qt::DisplayRole)
    {
        switch (section)
        {
        case column_name:
            return tr("name");
            break;
        case column_age:
            return tr("age");
            break;
        case column_height:
            return tr("height");
            break;
        case column_weight:
            return tr("weight");
            break;
        }
    }
    return QVariant();
}

QVariant StudentModel::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    int col = index.column();
    auto info = m_studentList.at(row);
    if (role == Qt::DisplayRole)
    {
        switch (col)
        {
        case column_name:
            return info.name;
            break;
        case column_age:
            return QString::number(info.age);
            break;
        case column_height:
            return QString::number(info.height);
            break;
        case column_weight:
            return QString::number(info.weight);
            break;
        }
    }
    else if (role == Qt::UserRole)
    {
        return QVariant::fromValue<Student>(m_studentList[row]);
    }
    return QVariant();
}
3、添加筛选过滤model文件, studentproxymodel.h,studentproxymodel.cpp
studentproxymodel.h


#include <QSortFilterProxyModel>
#include "studentmodel.h"

class StudentProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT
public:
    explicit StudentProxyModel(QObject *parent = nullptr);

protected:
    // 返回true表示source的资源包含在代理model中
    virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;

};

#include "studentproxymodel.h"

StudentProxyModel::StudentProxyModel(QObject *parent)
    : QSortFilterProxyModel{parent}
{

}

bool StudentProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
    QModelIndex source = sourceModel()->index(source_row, 0, source_parent);
    // 资源Enttiy节点进行过滤
    Student student = source.data(Qt::UserRole).value<Student>();
    //过滤条件:如果年龄小于20,或身高小于170,或体重小于50,则不显示,返回false
    if(student.age < 20)
    {
        return false;
    }
    if(student.height < 170)
    {
        return false;
    }
    if(student.weight < 50)
    {
        return false;
    }
    return true;
}

4、在widget.cpp中添加测试代码
widget.cpp


#include "widget.h"
#include "ui_widget.h"
#include <QTableView>
#include <QBoxLayout>
#include "studentmodel.h"
#include "studentproxymodel.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QHBoxLayout* layout = new QHBoxLayout(this);
    this->setLayout(layout);
    QTableView* tableView = new QTableView(this);
    layout->addWidget(tableView);

    Student stu1;
    stu1.age = 18;
    stu1.name = "sandy";
    stu1.height = 170;
    stu1.weight = 50;

    Student stu2;
    stu1.age = 23;
    stu1.name = "alice";
    stu1.height = 168;
    stu1.weight = 55;

    Student stu3;
    stu1.age = 20;
    stu1.name = "make";
    stu1.height = 178;
    stu1.weight = 60;

    Student stu4;
    stu1.age = 22;
    stu1.name = "jason";
    stu1.height = 180;
    stu1.weight = 70;

    QList<Student> studentList;
    studentList.clear();
    studentList.append(stu1);
    studentList.append(stu2);
    studentList.append(stu3);
    studentList.append(stu4);

    StudentModel* model = new StudentModel(this);
    StudentProxyModel* proxyModel = new StudentProxyModel(this);
    proxyModel->setSourceModel(model);
    tableView->setModel(proxyModel);
    model->setInfo(studentList);
}

Widget::~Widget()
{
    delete ui;
}
5、结果显示满足过滤条件(只有make和jason满足过滤条件)

在这里插入图片描述

如果您不想使用QSortFilterProxyModel,您可以手动过滤模型的数据。以下是一个简单的示例,演示如何在不继承QSortFilterProxyModel的情况下实现双重过滤: ```cpp // 创建一个自定义的模型类 class CustomModel : public QAbstractListModel { public: CustomModel(QObject *parent = nullptr); // 重写rowCount函数,返回模型数 int rowCount(const QModelIndex &parent = QModelIndex()) const override; // 重写data函数,返回模型指定索引的数据 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; // 添加两个过滤函数,用于过滤模型的数据 void setFirstFilter(QString filter); void setSecondFilter(QString filter); private: // 存储模型的数据 QList<QString> m_data; // 存储两个过滤器 QString m_firstFilter; QString m_secondFilter; }; CustomModel::CustomModel(QObject *parent) : QAbstractListModel(parent) { // 初始化模型的数据 m_data << "apple" << "banana" << "orange" << "peach" << "grape"; } int CustomModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_data.count(); } QVariant CustomModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (role == Qt::DisplayRole) return m_data.at(index.row()); return QVariant(); } void CustomModel::setFirstFilter(QString filter) { // 更新第一个过滤器 m_firstFilter = filter; // 过滤数据 QModelIndex topLeft = index(0, 0); QModelIndex bottomRight = index(m_data.count() - 1, 0); emit dataChanged(topLeft, bottomRight); } void CustomModel::setSecondFilter(QString filter) { // 更新第二个过滤器 m_secondFilter = filter; // 过滤数据 QModelIndex topLeft = index(0, 0); QModelIndex bottomRight = index(m_data.count() - 1, 0); emit dataChanged(topLeft, bottomRight); } ``` 在这个示例,我们创建了一个名为CustomModel自定义模型类,并添加了两个过滤函数setFirstFilter和setSecondFilter。这些函数将更新模型过滤器,并发出dataChanged信号以重新过滤模型的数据。 要使用这个模型,您可以将其设置为QListView或QTableView的模型,并连接过滤器控件的信号以调用setFirstFilter和setSecondFilter函数。 ```cpp CustomModel *model = new CustomModel(this); QListView *view = new QListView(this); view->setModel(model); QLineEdit *firstFilterEdit = new QLineEdit(this); connect(firstFilterEdit, &QLineEdit::textChanged, model, &CustomModel::setFirstFilter); QLineEdit *secondFilterEdit = new QLineEdit(this); connect(secondFilterEdit, &QLineEdit::textChanged, model, &CustomModel::setSecondFilter); ``` 此外,还可以在data函数添加过滤逻辑,以便只返回符合过滤条件的数据。这在处理大型数据集时可能更有效率,但需要更多的代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

commonbelive

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值