使用QSettings保存QTreeView目录展开状态失败,主窗口状态正常
解决QTreeView展开/折叠状态的保存与恢复问题
原代码仅实现了窗口大小、位置和表头状态的保存,未处理树节点的展开/折叠状态。以下是修正后的方案:
核心思路
QTreeView没有直接保存节点展开状态的方法,我们可以利用QFileSystemModel的特性——每个节点索引对应唯一的文件路径,通过记录所有展开节点的路径,重启后再通过路径定位节点并恢复展开状态。同时要注意QFileSystemModel是异步加载的,需等待目录加载完成后再执行恢复操作。
修正后的完整代码
import sys from PyQt5.QtCore import QSettings, Qt from PyQt5.QtWidgets import QApplication, QTreeView, QFileSystemModel, QVBoxLayout, QWidget class MyApp(QWidget): def __init__(self): super().__init__() self.tree = QTreeView() self.settings = QSettings('testorg', 'testapp') # 初始化窗口状态 try: self.resize(self.settings.value('window size')) self.move(self.settings.value('window position')) except: pass # 初始化文件系统模型和树视图 self.model = QFileSystemModel() # 修正原路径错误:移除多余的>符号 self.root_path = r"C:\Users\dan-s" self.model.setRootPath(self.root_path) self.tree.setModel(self.model) self.tree.setRootIndex(self.model.index(self.root_path)) # 恢复表头状态 try: header_state = self.settings.value("estado_header") if header_state is not None: self.tree.header().restoreState(header_state) except: pass # 等待根目录加载完成后恢复展开状态 self.model.directoryLoaded.connect(self.restore_expanded_state) layout = QVBoxLayout() layout.addWidget(self.tree) self.setLayout(layout) def restore_expanded_state(self, path): # 仅在根目录加载完成后执行恢复逻辑 if path != self.root_path: return # 读取保存的展开路径列表 expanded_paths = self.settings.value("expanded_paths", []) if not expanded_paths: return # 遍历路径,找到对应索引并展开节点 for path in expanded_paths: index = self.model.index(path) if index.isValid(): self.tree.expand(index) # 断开信号,避免重复触发 self.model.directoryLoaded.disconnect(self.restore_expanded_state) def get_expanded_paths(self): # 遍历所有展开的节点,收集对应的文件路径 expanded_paths = [] def traverse(index): if self.tree.isExpanded(index): expanded_paths.append(self.model.filePath(index)) # 递归遍历子节点 for row in range(self.model.rowCount(index)): child_index = self.model.index(row, 0, index) traverse(child_index) # 从树视图的根节点开始遍历 traverse(self.tree.rootIndex()) return expanded_paths def closeEvent(self, event): # 保存窗口大小与位置 self.settings.setValue('window size', self.size()) self.settings.setValue('window position', self.pos()) # 保存表头状态 header_state = self.tree.header().saveState() self.settings.setValue('estado_header', header_state) # 保存所有展开节点的路径 expanded_paths = self.get_expanded_paths() self.settings.setValue("expanded_paths", expanded_paths) super().closeEvent(event) if __name__ == "__main__": app = QApplication(sys.argv) demo = MyApp() demo.show() sys.exit(app.exec_())
关键修改点
- 修正了原代码中根路径的错误(移除了多余的
>符号) - 添加
get_expanded_paths()方法,递归遍历所有展开节点并收集对应文件路径 - 添加
restore_expanded_state()方法,在根目录加载完成后,通过保存的路径恢复节点展开状态 - 在
closeEvent中新增保存展开路径的逻辑 - 利用
directoryLoaded信号确保模型加载完成后再执行恢复操作,避免出现索引无效的问题
内容的提问来源于stack exchange,提问作者Danilo Silva
相关产品推荐
相关产品推荐

