- QTreeWidget 是管理类似目录之类,树结构的类。
- QTreeWidget 每个节点可有多列,节点层次可以嵌套。
- QTreeWidget 每个节点是 QTreeWidgetItem。
- QTreeWidget 每个节点可设置类型,文本,字体,图标,还有自定义数据,是否展开,是否selected,CheckState,flags属性(设置节点是否可选、是否可编辑、是否有CheckBox)。
- 在构造函数传递一个类型值,QTreeWidgetItem.type()函数可以返回这个类型值。
- QTreeWidget 分为 顶层节点(TopLevelItem)和非顶层节点。
- 通过 addTopLevelItem 添加顶层节点。
- 顶层节点和非顶层节点通过 addChild 添加子节点 或者 子节点指定父类。
- removeChild() 函数用于移除一个节点及其所有子节点。有很多关于child的函数
- 删除顶层节点,使用 QTreeWidget.takeTopLevelItem(index) 函数。
- 遍历节点 或者 要访问所有顶层节点,需要 topLevelItemCount() 和 topLevelItem(index)。
- QTreeWidget 信号
- 事件如图
- itemPressed 是鼠标按下未松开。
- itemClicked 是鼠标按下并弹起。
以下是个例子,该例子遍历文件夹展示到QTreeWidget中 :
#!/usr/bin/env python # -*- coding: utf-8 -*- """ @author: wind @contact: 367059791@qq.com @time: 2022/2/24 13:46 @file: demo_qtreewidget.py @desc: """ import sys import os from os import path as osp from enum import Enum, unique from PySide2.QtWidgets import ( QTreeWidget, QApplication, QWidget, QPushButton, QVBoxLayout, QFileDialog, QTreeWidgetItem, QStyle ) from PySide2.QtCore import Qt @unique class NodeType(Enum): """节点类型,文件还是文件夹""" NodeDir = 0 NodeFile = 1 class DemoTreeWidget(QWidget): def __init__(self, parent=None): super(DemoTreeWidget, self).__init__(parent) self.setFixedSize(600, 400) self.setWindowTitle("DemoTreeWidget") self.project_tree = QTreeWidget(self) self.btn_load = QPushButton("加载工程", self) self.init_layout() self.init_ctl() def init_ctl(self): self.btn_load.clicked.connect(self.load_project) self.project_tree.header().setVisible(False) # 隐藏表头 def init_layout(self): v_layout = QVBoxLayout() v_layout.addWidget(self.project_tree) v_layout.addWidget(self.btn_load, alignment=Qt.AlignRight) self.setLayout(v_layout) def load_project(self): directory = QFileDialog.getExistingDirectory(self, "选择工程目录", ".", QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) if not directory: return top_item = self.create_top_item(directory) # 创建topitem self.list_dir(top_item, directory) # 递归遍历 def list_dir(self, parent, directory): for obj in os.listdir(directory): tmp_path = osp.join(directory, obj) if osp.isdir(tmp_path): dir_item = self._generate_item(parent, obj, tmp_path, NodeType.NodeDir.value) self.list_dir(dir_item, tmp_path) else: self._generate_item(parent, obj, tmp_path, NodeType.NodeFile.value) def _generate_item(self, parent, name, path, node_type): item = QTreeWidgetItem(parent, node_type) item.setText(0, name) item.setToolTip(0, path) item.setData(0, Qt.UserRole, path) item.setIcon(0, self.style().standardIcon(QStyle.SP_DirIcon if node_type == NodeType.NodeDir.value else QStyle.SP_FileIcon)) return item def create_top_item(self, project_path): if not project_path: return # root project_name = osp.basename(project_path) top_item = QTreeWidgetItem(self.project_tree, NodeType.NodeDir.value) top_item.setText(0, project_name) top_item.setToolTip(0, project_path) top_item.setData(0, Qt.UserRole, project_path) top_item.setIcon(0, self.style().standardIcon(QStyle.SP_DirIcon)) self.project_tree.addTopLevelItem(top_item) return top_item if __name__ == "__main__": app = QApplication(sys.argv) wnd = DemoTreeWidget() wnd.show() sys.exit(app.exec_())
想在切换到某个节点之前,判断一些条件,不满足就不切换,该如何处理呢?比如下图,想在切换到“第2场”前,判断第1场是否被修改过,若修改过就不切换,必须先保存,以免丢失修改内容。笔者尝试了 itemPressed和itemClicked没能成功,最后采用了 currentItemChanged 和 mousePressEvent 最后解决。有疑问可咨询。