如何在QListView中隐藏文件夹仅显示文件?解决视图重置问题
解决QListView设置文件过滤后重置到根目录的问题
问题原因
当你为mainListViewModel设置QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Files过滤规则后,该模型只会加载文件节点,不会加载文件夹节点。在update_main_list_view方法中,你传入的new_path是文件夹路径,调用self.mainListViewModel.index(new_path)时,模型无法找到该文件夹对应的索引,QListView就会默认切换到根目录(空路径)。
解决方案
不要直接修改QFileSystemModel的过滤规则,而是给QListView搭配QSortFilterProxyModel,通过代理模型过滤掉文件夹,只显示文件。这样源模型仍能正常识别文件夹路径,保证setRootIndex生效,同时视图只展示文件。
修改后的完整代码
from PySide2 import QtCore, QtWidgets class FileOnlyProxyModel(QtCore.QSortFilterProxyModel): def filterAcceptsRow(self, source_row, source_parent): source_model = self.sourceModel() index = source_model.index(source_row, 0, source_parent) # 只接受文件,过滤掉文件夹 return source_model.isFile(index) class AssetBrowser(QtWidgets.QWidget): def __init__(self): super(AssetBrowser, self).__init__() self.setWindowTitle("Tree and List View Example") self.setGeometry(100, 100, 400, 500) self.treeView = QtWidgets.QTreeView(self) self.mainListView = QtWidgets.QListView(self) self.search_line_edit = QtWidgets.QLineEdit(self) # Create the layout layout = QtWidgets.QVBoxLayout() layout.addWidget(self.treeView) layout.addWidget(self.mainListView) layout.addWidget(self.search_line_edit) # Create a central widget and set the layout central_widget = QtWidgets.QWidget(self) central_widget.setLayout(layout) ### treeViewViewStart self.treeViewModel = QtWidgets.QFileSystemModel() self.treeViewModel.setRootPath('') self.treeViewModel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.AllDirs) self.treeViewProxyModel = QtCore.QSortFilterProxyModel() self.treeViewProxyModel.setSourceModel(self.treeViewModel) self.treeView.setModel(self.treeViewProxyModel) self.treeView.setRootIndex(self.treeViewProxyModel.mapFromSource(self.treeViewModel.index("D:/"))) self.treeView.setColumnHidden(1, True) self.treeView.setColumnHidden(2, True) self.treeView.setColumnHidden(3, True) self.treeView.setHeaderHidden(True) self.treeView.clicked.connect(self.update_main_list_view) ### treeViewViewEnd ### listViewStart self.mainListViewModel = QtWidgets.QFileSystemModel() self.mainListViewModel.setRootPath('') # 源模型保留能识别文件夹和文件的过滤规则 self.mainListViewModel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.AllDirs | QtCore.QDir.Files) # 添加文件过滤代理 self.listViewProxyModel = FileOnlyProxyModel() self.listViewProxyModel.setSourceModel(self.mainListViewModel) self.mainListView.setIconSize(QtCore.QSize(100, 100)) self.mainListView.setViewMode(QtWidgets.QListView.IconMode) self.mainListView.setResizeMode(QtWidgets.QListView.Adjust) self.mainListView.setMovement(QtWidgets.QListView.Static) ### listViewEnd # 给ListView设置代理模型 self.mainListView.setModel(self.listViewProxyModel) # 转换索引到代理模型 source_index = self.mainListViewModel.index("D:/") proxy_index = self.listViewProxyModel.mapFromSource(source_index) self.mainListView.setRootIndex(proxy_index) def update_main_list_view(self, index): selected_index = self.treeViewProxyModel.mapToSource(index) new_path = self.treeViewModel.filePath(selected_index) print(new_path) # 获取源模型的索引,转换为代理模型的索引后设置 source_index = self.mainListViewModel.index(new_path) proxy_index = self.listViewProxyModel.mapFromSource(source_index) self.mainListView.setRootIndex(proxy_index) if __name__ == "__main__": app = QtWidgets.QApplication([]) window = AssetBrowser() window.show() app.exec_()
关键修改点
- 自定义
FileOnlyProxyModel,重写filterAcceptsRow方法,只接受文件节点。 mainListViewModel的过滤规则改为包含文件夹和文件,保证能识别文件夹路径。- QListView使用代理模型,设置根索引时需要将源模型的索引转换为代理模型的索引。
- 在
update_main_list_view方法中,同样需要将源模型的路径索引转换为代理模型的索引后再设置给ListView。
内容的提问来源于stack exchange,提问作者wayfarer
相关产品推荐
相关产品推荐

