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

QT 5.10递归过滤系统文件问题:QSortFilterProxyModel子文件不显示

解决QSortFilterProxyModel递归过滤文件时子文件不显示的问题

我刚好踩过这个坑!你的核心问题出在QSortFilterProxyModel的默认行为上:如果父文件夹被过滤掉,它的所有子项都会被自动隐藏;而且如果不对文件夹的过滤逻辑做特殊处理,子文件甚至没机会进入你的过滤判断流程。下面是完整的修复方案:

第一步:自定义代理模型,重写过滤逻辑

你需要继承QSortFilterProxyModel,并重写filterAcceptsRow方法,专门区分文件夹和文件的过滤规则:

#include <QSortFilterProxyModel>
#include <QFileSystemModel>

class FileFilterProxyModel : public QSortFilterProxyModel
{
protected:
    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
    {
        // 获取源文件系统模型
        QFileSystemModel* fileModel = qobject_cast<QFileSystemModel*>(sourceModel());
        if (!fileModel) return false;

        // 获取当前行的源索引
        QModelIndex sourceIndex = fileModel->index(source_row, 0, source_parent);
        
        // 关键:文件夹直接放行
        // 只有文件夹能通过过滤,它下面的子文件才会被评估是否显示
        if (fileModel->isDir(sourceIndex)) {
            return true;
        }

        // 这里写你的文件过滤规则,示例:只显示txt格式文件
        QString fileName = fileModel->fileName(sourceIndex);
        return fileName.endsWith(".txt", Qt::CaseInsensitive);
    }
};

第二步:在主程序中使用自定义代理模型

替换原来的逻辑,注意要正确转换根索引:

#include <QApplication>
#include <QMainWindow>
#include <QTreeView>
#include <QFileSystemModel>

// 上面的FileFilterProxyModel定义放在这里或者单独头文件

int main(int argc, char **argv)
{
    QString path = "C:/";
    QApplication app(argc, argv);
    QMainWindow window;
    QTreeView* treeView = new QTreeView(&window);

    // 初始化文件系统模型
    QFileSystemModel model;
    model.setRootPath(path);
    // 设置显示规则:显示所有条目,隐藏.和..
    model.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);

    // 使用自定义代理模型
    FileFilterProxyModel proxyModel;
    proxyModel.setSourceModel(&model);
    // 如果需要用字符串过滤,也可以用setFilterFixedString/setFilterRegExp
    // proxyModel.setFilterFixedString(".txt");

    // 给TreeView绑定代理模型
    treeView->setModel(&proxyModel);
    // 关键:将源模型的根索引转换为代理模型的索引
    QModelIndex proxyRootIndex = proxyModel.mapFromSource(model.index(path));
    treeView->setRootIndex(proxyRootIndex);

    window.setCentralWidget(treeView);
    window.resize(800, 600);
    window.show();

    return app.exec();
}

关键要点解释

  1. 文件夹必须放行:这是子文件能显示的核心!如果文件夹被过滤掉,QSortFilterProxyModel会直接跳过它的所有子项,根本不会调用filterAcceptsRow去判断子文件。
  2. 根索引转换:不能直接把QFileSystemModel的索引传给TreeView,必须用mapFromSource转换成代理模型的索引,否则会出现显示异常。
  3. 灵活调整过滤规则:如果你的需求不是过滤后缀,而是文件名包含特定字符、文件大小等规则,只需要修改文件判断部分的代码即可。

如果需要同时过滤文件夹,那你要调整文件夹的判断逻辑——比如只有符合条件的文件夹才放行,但要注意:如果父文件夹被过滤,它的所有子项都会被隐藏,这种情况下递归过滤文件夹需要更复杂的逻辑(比如向上遍历父节点判断是否被接受)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:55:15