逆枫゛

Qt学习群:1149411109 群文件提供博客源码,定期答疑、更新学习资料。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1,简介

有时候需要对tree内的数据按一些条件进行过滤显示,比如按搜索条件过滤,这时候就用到了代理model。
通常使用Qt提供的 QSortFilterProxyModel 类,该类实现了常见的按行列过滤的方法。
也可以自己从基类继承,重写 filterAcceptsRow 和 filterAcceptsColumn 来实现过滤:

virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
virtual bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const;

重写 lessThan 方法可实现排序:

virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;

本文先介绍直接使用QSortFilterProxyModel 类接口完成常见过滤功能的方法,后面介绍继承该类自定义过滤规则的方法。

2,参考资料

官方示例:在QtCreator的欢迎里搜“QSortFilterProxyModel”,出现2个示例。
Basic Sort/Filter Model Example 基础排序/过滤模型示例
Custom Sort/Filter Model Example 自定义排序/过滤模型示例

3,效果

这里写图片描述

4,实现

相比之前正常构造QTreeView的model的过程,这里需要新建一个QSortFilterProxyModel对象,并且设其源model为我们之前原始的model。然后把tree的model设为该QSortFilterProxyModel。
这样tree在显示时先访问该QSortFilterProxyModel,通过其提供的过滤规则最后从真实的model里面取数据进行显示,实现数据过滤。

主要代码如下:

void MainWindow::InitTree()
{
    //1,QTreeView常用设置项
    QTreeView* t = ui->treeView;
//    t->setEditTriggers(QTreeView::NoEditTriggers);            //单元格不能编辑
    t->setSelectionBehavior(QTreeView::SelectRows);         //一次选中整行
    t->setSelectionMode(QTreeView::SingleSelection);        //单选,配合上面的整行就是一次选单行
//    t->setAlternatingRowColors(true);                       //每间隔一行颜色不一样,当有qss时该属性无效
    t->setFocusPolicy(Qt::NoFocus);                         //去掉鼠标移到单元格上时的虚线框

    //2,列头相关设置
    t->header()->setHighlightSections(true);                //列头点击时字体变粗,去掉该效果
    t->header()->setDefaultAlignment(Qt::AlignCenter);      //列头文字默认居中对齐
    t->header()->setDefaultSectionSize(100);                //默认列宽100
    t->header()->setStretchLastSection(true);               //最后一列自适应宽度
    t->header()->setSortIndicator(0,Qt::AscendingOrder);    //按第1列升序排序

    //3,构造Model
    //设置列头
    QStringList headers;
    headers << QStringLiteral("年级/班级")
            << QStringLiteral("姓名")
            << QStringLiteral("分数")
            << QStringLiteral("评价");
    mModel = new QStandardItemModel(ui->treeView);
    mModel->setHorizontalHeaderLabels(headers);
    //设置数据
    QStringList names;
    names<<"aaa"<<"bbb"<<"ccc"<<"ddd"<<"eee"<<"abc"<<"abcdef";
    for(int i=0; i<names.size(); i++)
    {
        //二级节点:班级、姓名、分数
        QList<QStandardItem*> items;
        QStandardItem* itemClass = new QStandardItem(QStringLiteral("%1班").arg(i+1));
        QStandardItem* itemName = new QStandardItem(names.at(i));
        QStandardItem* itemScore = new QStandardItem("100");
        QStandardItem* itemAssess = new QStandardItem("优");
        items << itemClass << itemName << itemScore << itemAssess;
        mModel->appendRow(items);    //二级节点挂在一级的第1列节点上
    }
    //4,构造代理model,设置过滤列为第2列
    mProxyModel = new QSortFilterProxyModel;
    mProxyModel->setSourceModel(mModel);
    mProxyModel->setFilterKeyColumn(1);
    t->setModel(mProxyModel);
}

三个按钮设置三种不同的过滤形式:
根据正则表达式、通配符、普通文本

void MainWindow::on_btn1_clicked()
{
    //正则表达式
    //包含a、b、c中任意一个字符就满足
    QRegExp regExp("[abc]", Qt::CaseInsensitive, QRegExp::RegExp);
    mProxyModel->setFilterRegExp(regExp);
}

void MainWindow::on_btn2_clicked()
{
    //通配符
    //有bc的满足
    QRegExp regExp("bc*", Qt::CaseInsensitive, QRegExp::Wildcard);
    mProxyModel->setFilterRegExp(regExp);
}

void MainWindow::on_btn3_clicked()
{
    //文本
    //包含文本e的满足
    QRegExp regExp("e", Qt::CaseInsensitive, QRegExp::FixedString);
    mProxyModel->setFilterRegExp(regExp);
}

5,源码

本示例源码下载:

https://pan.baidu.com/s/1lG-B_dR9Tnn-BoBzVQ62WA

posted on 2018-05-20 17:11  逆枫゛  阅读(626)  评论(0编辑  收藏  举报