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,源码
本示例源码下载: