目录
一、自定义控件(读者可直接Copy)
import os
import platform
from PySide6 import QtWidgets
from PySide6.QtCore import QObject, Signal, Qt
from PySide6.QtGui import QIcon
from PySide6.QtWidgets import QWidget, QVBoxLayout, QTreeWidget, QApplication, QTreeWidgetItem
class TreeWidgetItem:
def __init__(self, id: any, parent_id: any, name: str, icon: QIcon = None, extend: object = None):
"""
菜单数据接口
:param id: ID
:param parent_id: 父ID
:param name: 菜单名称
:param icon: 图标
:param extend: 扩展数据
"""
self.id: any = id
self.parent_id: any = parent_id
self.name: str = name
self.extend: object = extend
# 实例化
self.treeWidgetItem = QTreeWidgetItem([self.name])
# 存储相关数据
self.treeWidgetItem.setData(0, Qt.UserRole + 1, extend)
self.treeWidgetItem.setIcon(0, QIcon(':/icons/default.png'))
if icon is not None:
self.treeWidgetItem.setIcon(0, icon)
class ElTreeData(QObject):
"""
Data Model
"""
items_changed: Signal = Signal(str)
styleSheet_changed: Signal = Signal(str)
def __init__(self, items: list[TreeWidgetItem] = None, styleSheet: str = None):
super(ElTreeData, self).__init__()
# 定义数据
self._items: list[TreeWidgetItem]
self._styleSheet: str
# 初始化数据
self.items = items
self.styleSheet = styleSheet
@property
def items(self):
return self._items
@items.setter
def items(self, value):
self._items = value
# 数据改变时发出信号
self.items_changed.emit(self.items)
@property
def styleSheet(self):
return self._styleSheet
@styleSheet.setter
def styleSheet(self, value):
self._styleSheet = value
# 数据改变时发出信号
self.styleSheet_changed.emit(self.styleSheet)
"""
初始化CSS文件位置
"""
CSS_PATH = None
if str(platform.system().lower()) == 'windows':
path = __file__.replace(fr"\{os.path.basename(__file__)}", "").replace("\\\\", "\\")
CSS_PATH = fr'{path}\el_tree.css'
elif str(platform.system().lower()) == 'linux':
path = __file__.replace(fr"/{os.path.basename(__file__)}", "").replace("//", "/")
CSS_PATH = fr'{path}/el_tree.css'
else:
print(f"未知系统:{platform.system().lower()}")
class ElTreeUi(object):
"""
User Interface
"""
def setupUi(self, window):
with open(CSS_PATH, "r", encoding="UTF-8") as f:
window.setStyleSheet(f.read())
window.setWindowTitle("ElTree")
window.setWindowIcon(QIcon(':/icons/add.png'))
window.resize(40, 30)
# 设置整个窗体的透明度
window.setWindowOpacity(0.90) # 设置窗体透明度
# 设置隐藏背景
window.setAttribute(Qt.WA_TranslucentBackground)
# 垂直布局
self.layout = QVBoxLayout()
# 设置边距为0
self.layout.setContentsMargins(0, 0, 0, 0)
window.setLayout(self.layout)
self._tree = QTreeWidget()
self._tree.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding)
self.layout.addWidget(self._tree)
class ElTree(QWidget, ElTreeUi):
"""
Control
"""
itemClicked: Signal = Signal(object)
itemDoubleClicked: Signal = Signal(object)
def __init__(self, treeData: ElTreeData, parent=None):
super(ElTree, self).__init__(parent=parent)
self.setupUi(self)
self.data = treeData
self.__bind()
# 将按钮的点击信号绑定到当前类的点击信号
self._tree.itemClicked.connect(lambda item: self.itemClicked.emit(item.data(0, Qt.UserRole + 1)))
self._tree.itemDoubleClicked.connect(lambda item: self.itemDoubleClicked.emit(item.data(0, Qt.UserRole + 1)))
self.__render_items(True)
def __render_items(self, is_clear: bool):
if is_clear:
self._tree.clear()
self._tree.setColumnCount(1)
self._tree.setHeaderHidden(True)
if self.data.items is not None:
# 转为字典
mapping: dict[any, TreeWidgetItem] = dict(zip([i.id for i in self.data.items], self.data.items))
# 树容器
treeWidgetItems: list[QTreeWidgetItem] = []
for d in self.data.items:
# 如果找不到父级项,则是根节点
parent: TreeWidgetItem = mapping.get(d.parent_id)
if parent is None:
treeWidgetItems.append(d.treeWidgetItem)
else:
parent.treeWidgetItem.addChild(d.treeWidgetItem)
# 挂载到树上
self._tree.insertTopLevelItems(0, treeWidgetItems)
def __bind(self):
"""
数据绑定到控件属性
"""
pass
二、使用案例
if __name__ == '__main__':
"""
Test Demo
"""
# 引入资源(这一步不能少!)
from images.resources_rc import *
app = QApplication([])
button = ElTree(ElTreeData(items=[
TreeWidgetItem(1, 0, "User", icon=QIcon(":/icons/add.png"), extend={'id': 1}),
TreeWidgetItem(2, 1, "Child", icon=QIcon(":/icons/address.png"), extend={'id': 2}),
TreeWidgetItem(3, 1, "Child", icon=QIcon(":/icons/code_generator.png"), extend={'id': 3}),
TreeWidgetItem(4, 2, "Child", icon=QIcon(":/icons/linked.png"), extend={'id': 4}),
TreeWidgetItem(5, 2, "Child", icon=QIcon(":/icons/template.png"), extend={'id': 5}),
TreeWidgetItem(6, 5, "Child", icon=QIcon(":/icons/template_edit.png"), extend={'id': 6}),
TreeWidgetItem(7, 5, "Child", extend={'id': 7}),
TreeWidgetItem(8, 5, "Child", extend={'id': 8}),
TreeWidgetItem(9, 8, "Child", extend={'id': 9}),
]))
button.itemClicked.connect(lambda extend: print("单击->扩展数据为:", extend))
button.itemDoubleClicked.connect(lambda extend: print("双击->扩展数据为:", extend))
button.show()
app.exec()