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

如何创建仅展示指定文件列表的QFileSystemModel并修正筛选逻辑反向问题?

解决QFileSystemModel筛选指定文件列表及反向筛选问题

首先,咱们先解决你当前遇到的点击左侧文件后右侧同名文件消失的问题——这完全是因为你的filterAcceptsRow逻辑写反了!你现在的代码是当文件名匹配时返回False(把匹配的文件过滤掉),而我们需要的是匹配时返回True(只保留匹配的文件)。

第一步:修正反向筛选逻辑

修改你的modifiedQSortFilterProxyModel中的filterAcceptsRow方法,把判断条件反转:

def filterAcceptsRow(self, source_row, source_parent):
    filename = self.sourceModel().index(source_row, 0, source_parent).data()
    # 现在只保留和目标文件名匹配的文件
    if filename == self.file:
        return True
    else:
        return False

这样修改后,当你点击左侧的文件时,右侧TreeView就只会显示同名的文件了,完全符合你的预期。

第二步:扩展支持显示指定文件列表

如果你需要展示的是一个固定文件列表(比如你提到的main_file1 = ["[053ALO] - test file.txt", ...]),我们可以进一步扩展proxy model,让它支持接收一个允许显示的文件列表,而不是单个文件名:

class modifiedQSortFilterProxyModel(QSortFilterProxyModel):
    def __init__(self):
        super().__init__()
        self.file = ''
        # 添加属性存储允许显示的文件列表
        self.allowed_files = []

    def filterAcceptsRow(self, source_row, source_parent):
        filename = self.sourceModel().index(source_row, 0, source_parent).data()
        # 优先使用文件列表筛选,如果列表不为空,则只保留列表中的文件
        if self.allowed_files:
            return filename in self.allowed_files
        # 如果列表为空,再使用单个文件名匹配逻辑
        elif self.file:
            return filename == self.file
        # 默认显示所有文件
        else:
            return True

之后你可以直接设置这个列表来展示指定文件:

# 示例:设置要显示的文件列表
self.filter_proxy_model.allowed_files = ["[053ALO] - test file.txt", "[053ALO] - test file.txt", "[053ALO] - test file.txt"]
self.filter_proxy_model.invalidateFilter()

完整修正后的代码

把这些修改整合到你的代码中,最终版本如下:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTreeView, QFileSystemModel, QHBoxLayout
from PyQt5.QtCore import QSortFilterProxyModel, Qt

class modifiedQSortFilterProxyModel(QSortFilterProxyModel):
    def __init__(self):
        super().__init__()
        self.file = ''
        self.allowed_files = []

    def filterAcceptsRow(self, source_row, source_parent):
        filename = self.sourceModel().index(source_row, 0, source_parent).data()
        if self.allowed_files:
            return filename in self.allowed_files
        elif self.file:
            return filename == self.file
        else:
            return True

class FileSystemView(QWidget):
    def __init__(self):
        super().__init__()
        appWidth = 800
        appHeight = 300
        self.setWindowTitle('File System Viewer')
        self.setGeometry(300, 300, appWidth, appHeight)
        dir_path = r'<Your directory>'  # 替换成你的目标目录

        # -- left -- #
        self.model = QFileSystemModel()
        self.model.setRootPath(dir_path)

        self.tree = QTreeView()
        self.tree.setModel(self.model)
        self.tree.setRootIndex(self.model.index(dir_path))
        self.tree.setColumnWidth(0, 250)
        self.tree.setAlternatingRowColors(True)
        self.tree.clicked.connect(self.onClicked)

        # -- right -- #
        self.model2 = QFileSystemModel()
        self.model2.setRootPath(dir_path)

        self.filter_proxy_model = modifiedQSortFilterProxyModel()
        self.filter_proxy_model.setSourceModel(self.model2)
        self.filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.filter_proxy_model.setDynamicSortFilter(True)
        self.filter_proxy_model.setFilterKeyColumn(0)

        root_index = self.model2.index(dir_path)
        proxy_index = self.filter_proxy_model.mapFromSource(root_index)

        self.tree2 = QTreeView()
        self.tree2.setModel(self.filter_proxy_model)
        self.tree2.setRootIndex(proxy_index)
        self.tree2.setColumnWidth(0, 250)
        self.tree2.setAlternatingRowColors(True)

        # 可选:初始化时显示指定文件列表
        # self.filter_proxy_model.allowed_files = ["[053ALO] - test file.txt", "[053ALO] - test file.txt", "[053ALO] - test file.txt"]
        # self.filter_proxy_model.invalidateFilter()

        # -- layout -- #
        layout = QHBoxLayout()
        layout.addWidget(self.tree)
        layout.addWidget(self.tree2)
        self.setLayout(layout)

    def onClicked(self, index):
        path = self.sender().model().fileName(index)
        # 点击时清空文件列表,切换为单个文件名匹配模式
        self.filter_proxy_model.allowed_files = []
        self.filter_proxy_model.file = path
        self.filter_proxy_model.invalidateFilter()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = FileSystemView()
    demo.show()
    sys.exit(app.exec_())

关键说明

  • 使用QSortFilterProxyModel是正确的做法:QFileSystemModel本身不支持自定义筛选,通过代理模型包装它,既能保留原模型提供的文件图标、大小/修改时间等详细信息,又能实现自定义筛选逻辑。
  • invalidateFilter():每次修改筛选条件后必须调用这个方法,触发代理模型重新计算筛选结果,否则界面不会更新。
  • 优先级逻辑:我们设置了文件列表优先于单个文件名的筛选规则,你可以根据场景灵活切换——比如初始化时显示指定列表,点击左侧文件后切换到显示同名文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 18:32:28