tkinter绘制组件(50)——高级树状图
- 引言
- 节点元素
- 高级树状图控件
- 获取当前选中元素
- 添加节点
- 删除节点
- 重命名节点
- 折叠、展开所有
- 事件绑定
- 面板布局
- 效果
- github项目
- pip下载
引言
在tkinter绘制组件(36)——树状图_tkinter树形结构-CSDN博客详细给出了TinUI初版树状图的构建方法。TinUI原生treeview基本没有任何交互能力,仅仅是数据结构的一种可视化展示。由于树状图的复杂性,即便极尽简化,为了使其具有基本交互能力,也不适用于在TinUI标准内容中进行功能添加。因此,一个更加高级的TinUI树状图控件在Smart-Space/TinUITreeview: TinUI高级树状图控件中单独提供。
TinUITreeview为独立项目,使用pip安装:pip install tinuitreeview
如上文所说,树状图仍然是TinUI迄今为止最复杂的控件,而且这个“上位替代”继承了原生树状图的主要构建方法,因此,本文基本上只讲怎么用。
节点元素
TinUITreeview内部使用节点元素来表示每个节点,其类型:
classTinUITreeItem:""" 代表树中的一个节点,持有画布对象 id 以及父/子关系。 属性(只读,由 TinUITreeView 维护): text - 节点显示文本 back - 背景矩形画布 id(也是 items 字典的键) te - 文字画布 id sign - 展开/收起三角图标画布 id(叶节点为 None) parent - 父 TinUITreeItem,根节点为 None children - 子 TinUITreeItem 列表 """def__init__(self,text:str,back,te,sign=None,parent=None):self.text:str=text self.back=back# 背景self.te=te# 文字self.sign=sign# 折叠图标,叶节点为 Noneself.parent:TinUITreeItem|None=parent self.children:list[TinUITreeItem]=[]注释里面也提到,使用者几乎不需要关心这个类是什么,但是其下成员属性仍可由使用者随时获取。
高级树状图控件
classTinUITreeView:_ICON_OPEN="\ue96e"_ICON_CLOSED="\ue970"def__init__(self,master:BasicTinUI,pos:tuple,fg="#1a1a1a",bg="#f3f3f3",onfg="#1a1a1a",onbg="#eaeaea",oncolor="#3041d8",signcolor="#8a8a8a",width=200,height=300,font="微软雅黑 12",content=(("one",("1","2","3")),"two",("three",("a",("b",("b1","b2","b3")),"c")),"four",),anchor="nw",command=None,):#...其初始化参数与原生treeview一模一样,基本可以无缝切换。
需要注意的是,command回调函数必须接受一个参数,即选中项的路径,确切来说,就是一个TinUITreeItem列表,从最高级节点到选中节点。
获取当前选中元素
get_selected(self)->TinUITreeItem|None通过调用该方法,可获取当前选中的元素。
添加节点
add_node(self,text:str,parent:TinUITreeItem|None=None,)->TinUITreeItem当parent为None时,即是向顶层末尾添加元素。如果parent存在且其本身是亲节点,则添加在下级末尾;否则会自动将其转为亲节点,并赋予展开与折叠功能。
会返回一个新建的元素。
删除节点
remove_node(self,item:TinUITreeItem)删除节点及其所有后代。
若被删节点是亲节点的最后一个子节点,则移除亲节点的折叠图标,删除其展开与折叠功能。
重命名节点
rename_node(self,item:TinUITreeItem,new_text:str)给指定元素重命名。
可以重名(当然,包括上级),树状图内部靠元素id进行关系管理,不过这是不必要的。
折叠、展开所有
defclose_all(self):foriteminlist(self._item_map.values()):ifitem.signandself._box.itemcget(item.sign,"text")==self._ICON_OPEN:self._close_view(item)defopen_all(self):foriteminlist(self._item_map.values()):ifitem.signandself._box.itemcget(item.sign,"text")==self._ICON_CLOSED:self._open_view(item)这部分同原生treeview。
事件绑定
defbind(self,sequence=None,func=None,add=None):"""绑定事件,代理给画布实现"""returnself._box.bind(sequence,func,add)defunbind(self,sequence,funcid=None):"""解绑事件,代理给画布实现"""self._box.unbind(sequence,funcid)面板布局
使用TinUITreeView.uid获取控件uid,用于TinUI面板布局。其行为与原生treeview一致。
效果
测试代码:
deftest(path):print("选中路径:"," > ".join(n.textforninpath))root=tk.Tk()tinui=BasicTinUI(root)tinui.pack(fill='both',expand=True)tree=TinUITreeView(tinui,(50,50),command=test)# 增new_item=tree.add_node("新节点")# 添加到根child=tree.add_node("子节点",parent=new_item)# 添加到指定节点下# 删# tree.remove_node(child) # 同时删除所有后代,父节点若变为空则自动降级为叶节点# 改tree.rename_node(new_item,"renamed")# 查# selected = tree.get_selected() # 返回 TinUITreeItem 或 None# print("当前选中:", selected)# 展开/折叠tree.close_all()root.after(2000,tree.open_all)# 2秒后展开所有节点rp=ExpandPanel(tinui,tree.uid)defon_resize(e):rp.update_layout(5,5,e.width-5,e.height-5)tinui.bind("<Configure>",on_resize)root.mainloop()github项目
TinUI的github项目地址
pip下载
pipinstalltinui