You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用QSortFilterProxyModel过滤时如何保留树形结构?

解决QSortFilterProxyModel过滤树形结构丢失层级的问题

我太懂这个坑了!用QSortFilterProxyModel过滤树形数据时,默认逻辑只会保留直接匹配的项,完全不管父节点的存在,这就是你只看到孤立Item 2的原因。另外你说获取父项返回null,大概率是没正确转换源模型索引导致的,我一步步给你解决:

核心问题分析

默认的filterAcceptsRows只检查当前行是否匹配过滤规则,但树形结构需要的是:只要当前项匹配,或者它的任意子节点(包括深层子节点)匹配,就应该保留当前项(父节点也要保留)。而且你之前获取父项返回null,是因为在代理模型的filterAcceptsRows方法里,直接用了代理模型的parent参数,得先转成源模型的索引才能正确拿到父节点。

解决方案代码实现

重写filterAcceptsRows时,改成递归检查当前项和所有子项的匹配情况,同时正确转换源模型索引:

bool CustomSortFilterProxyModel::filterAcceptsRows(int source_row, const QModelIndex &source_parent) const
{
    // 先拿到源模型中当前行的有效索引
    QModelIndex source_index = sourceModel()->index(source_row, filterKeyColumn(), source_parent);
    if (!source_index.isValid()) {
        return false;
    }

    // 检查当前项本身是否匹配过滤规则
    bool isMatch = sourceModel()->data(source_index).toString().contains(filterRegExp());

    // 如果当前项不匹配,递归遍历所有子项,只要有一个子项匹配就保留当前父项
    if (!isMatch) {
        int childCount = sourceModel()->rowCount(source_index);
        for (int i = 0; i < childCount; ++i) {
            if (filterAcceptsRows(i, source_index)) {
                isMatch = true;
                break;
            }
        }
    }

    // 返回最终匹配结果
    return isMatch;
}

关键细节说明

  1. 索引转换:必须用sourceModel()->index(...)获取源模型的索引,而不是直接用代理模型的索引,这样才能正确遍历树形结构的父节点和子节点,解决你之前父项返回null的问题。
  2. 递归检查:通过递归遍历子节点,确保只要有一个后代节点匹配,所有祖先节点都会被保留,完美还原你期望的树形层级。
  3. 性能提示:如果你的树形结构特别深或者节点数量极大,递归可能会有轻微性能损耗,这时可以考虑给匹配结果加个缓存(比如用QHash存储已检查过的索引状态),但绝大多数场景下直接递归就够用了。

用这个逻辑替换你原来的filterAcceptsRows实现,再用setFilterRegExp过滤含“2”的项,就能得到你想要的带完整层级的结果啦!

内容的提问来源于stack exchange,提问作者user2999980

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 08:07:51