如何在QFileSystemModel中过滤仅显示dcm文件及无扩展名文件
QFileSystemModel 过滤dcm文件与无扩展名文件实现方案
问题说明
导入PyQt相关依赖后,下述基础代码可正常运行:
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('MainWindow') self.layout = QHBoxLayout() self.file_system_widget = FileBrowser() self.layout.addWidget(self.file_system_widget) widget = QWidget() widget.setLayout(self.layout) self.setCentralWidget(widget) class FileBrowser(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): layout = QVBoxLayout() self.model = QFileSystemModel() self.model.setRootPath(self.model.myComputer()) self.model.setNameFilters(['*.*']) self.model.setNameFilterDisables(1) self.tree = QTreeView() self.tree.setModel(self.model) self.tree.setAnimated(False) self.tree.setSortingEnabled(True) layout.addWidget(self.tree) self.setLayout(layout) if __name__ == '__main__': app = QApplication(sys.argv) try: os.mkdir('Imports') except: pass main = MainWindow() main.show() app.exec()
代码运行后文件树默认展示所有类型文件,效果如下:
需求为修改过滤规则,仅展示两类内容:
- 扩展名为
.dcm的文件 - 无扩展名的文件
过滤掉其余带无关扩展名的文件,待过滤内容标注如下:
已知设置self.model.setNameFilters(['*.dcm'])可保留所有dcm格式文件,但无法匹配无扩展名文件,需要同时实现两类文件的过滤展示。
实现方案
QFileSystemModel原生的通配符过滤规则存在局限性,无法稳定跨平台匹配无扩展名文件,最稳妥的实现方式是自定义QSortFilterProxyModel代理模型,重写文件过滤判断逻辑:
- 自定义过滤代理类,目录默认放行保证文件夹可正常导航
- 文件维度判断:后缀为dcm、或者文件名不含
.(即无扩展名)的文件放行,其余文件过滤 - 将树视图绑定的模型替换为代理模型,完成源模型到代理模型的索引映射
完整修改代码
首先引入需要的依赖类:
from PyQt5.QtCore import QSortFilterProxyModel, QModelIndex, QFileInfo
新增自定义过滤代理类:
class FileFilterProxyModel(QSortFilterProxyModel): def filterAcceptsRow(self, source_row: int, source_parent: QModelIndex) -> bool: source_model = self.sourceModel() file_info = source_model.fileInfo(source_model.index(source_row, 0, source_parent)) # 目录始终放行,保证导航功能正常 if file_info.isDir(): return True # 放行.dcm后缀文件,不区分大小写 if file_info.suffix().lower() == "dcm": return True # 放行无扩展名文件 if "." not in file_info.fileName(): return True # 其余文件全部过滤 return False
修改FileBrowser类的initUI方法,替换为代理模型绑定逻辑:
def initUI(self): layout = QVBoxLayout() self.model = QFileSystemModel() self.model.setRootPath(self.model.myComputer()) # 初始化过滤代理,绑定源模型 self.filter_proxy = FileFilterProxyModel() self.filter_proxy.setSourceModel(self.model) self.tree = QTreeView() # 树视图绑定代理模型 self.tree.setModel(self.filter_proxy) # 根索引需要做代理映射 root_idx = self.model.index(self.model.myComputer()) self.tree.setRootIndex(self.filter_proxy.mapFromSource(root_idx)) self.tree.setAnimated(False) self.tree.setSortingEnabled(True) layout.addWidget(self.tree) self.setLayout(layout)
注意:不要尝试直接用通配符列表
['*.dcm', '*.']实现需求,该写法在Windows系统下无法正确识别无扩展名文件,兼容性极差,上述代理方案可在Windows、macOS、Linux全平台稳定生效。
内容的提问来源于stack exchange,提问作者温泽海
相关产品推荐
相关产品推荐

