如何为QStandardItemModel实现的树形结构添加过滤搜索功能
树形结构全局搜索实现方案
默认QSortFilterProxyModel仅检查当前行是否匹配过滤规则,无法实现父子节点全局搜索。通过重写filterAcceptsRow方法,可实现递归检查当前行、子节点及父节点的匹配情况,满足全局搜索需求。
自定义代理类实现
#include <QSortFilterProxyModel> #include <QModelIndex> class TreeFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override { // 检查当前行是否匹配 QModelIndex currentIndex = sourceModel()->index(source_row, filterKeyColumn(), source_parent); if (isMatch(currentIndex)) { return true; } // 递归检查所有子节点 for (int i = 0; i < sourceModel()->rowCount(currentIndex); ++i) { if (filterAcceptsRow(i, currentIndex)) { return true; } } // 递归检查父节点(保留匹配节点的上层层级) QModelIndex parentIndex = source_parent; while (parentIndex.isValid()) { if (isMatch(parentIndex)) { return true; } parentIndex = parentIndex.parent(); } return false; } private: bool isMatch(const QModelIndex &index) const { if (!index.isValid()) return false; QString itemText = sourceModel()->data(index, filterRole()).toString(); return itemText.contains(filterFixedString(), Qt::CaseInsensitive); } };
使用方式
将原有QSortFilterProxyModel替换为自定义代理类:
TreeFilterProxyModel *proxyModel = new TreeFilterProxyModel(this); proxyModel->setSourceModel(standardModel); proxyModel->setFilterRole(Qt::DisplayRole); // 指定过滤数据的角色 proxyModel->setFilterKeyColumn(0); // 过滤第0列内容 treeView->setModel(proxyModel); // 绑定搜索框与过滤规则 connect(searchLineEdit, &QLineEdit::textChanged, proxyModel, &TreeFilterProxyModel::setFilterFixedString);
可选优化
- 隐藏非匹配父节点:若无需保留匹配节点的上层层级,可删除检查父节点的代码块
- 大小写控制:将
Qt::CaseInsensitive改为Qt::CaseSensitive启用大小写敏感过滤 - 多列过滤:修改
isMatch方法,遍历多列数据进行匹配检查
内容的提问来源于stack exchange,提问作者Srikanth Reddy
相关产品推荐
相关产品推荐

