引言
顾名思义,这是一个可折叠的UI控件。
UI控件自然就是TinUI了,或者是不可滚动的BasicTinUI。
可折叠,就是说这个控件可以以一个标题框布局在某一个位置,使用者可以展开,查看其中的界面信息。
这种控件tkinter原生想都不敢想,虽然可以做到。
布局
函数结构
def add_expander(self,pos:tuple,title='expand content',tfg='black',tbg='#fbfbfb',bg='#f4f4f4',sep='#e5e5e5',width=200,height=200,scrollbar=False,font='微软雅黑 12'):#绘制一个可拓展UI
'''
pos-位置
title-标题
tfg-标题颜色
tbg-标题框颜色
bg-UI颜色
sep-边框、分割线颜色
width-UI宽度,标题宽度为 width-300
height-UI高度
scrollbar-是否启用TinUI
font-字体
'''
标题元素
这里的标题栏和TinUI的notify
类似,借鉴一下:
toptext=self.create_text((pos[0]+10,pos[1]+10),text=title,font=font,fill=tfg,width=width-30,anchor='nw')#标题
uid='expander'+str(toptext)
contentid='expander-content'+str(toptext)
self.addtag_withtag(uid,toptext)
self.addtag_withtag(contentid,toptext)
tx1,ty1,tx2,ty2=self.bbox(toptext)
if tx2-tx1<width:#判读当前文本宽度
tx2=tx1+width
topback=self.create_polygon((tx1,ty1,tx2,ty1,tx2,ty2,tx1,ty2),outline=tbg,fill=tbg,width=10,tags=(uid,contentid))#标题背景
需要注意的是,我们需要为折叠按钮提供一定的位置,因此文本宽度是width-30
。
当然这样的对于不同字号确实不妥,但是……坐等issue……
折叠按钮
button=self.add_button2((tx2-2,ty1-0.5),anchor='ne',text='🔻',font=font,fg=tfg,bg=tbg,activebg=bg,command=do_expand)
self.addtag_withtag(uid,button[-1])
self.addtag_withtag(contentid,button[-1])
折叠UI
这里简单区分一下TinUI和BasicTinUI。
if not scrollbar:#不使用滚动条,BasicTinUI
ui=BasicTinUI(self,bg=bg)
elif scrollbar:#使用TinUI
ui=TinUI(self,bg=bg)
ux=TinUIXml(ui)
content=self.create_window((tx1,ty2+10),window=ui,anchor='nw',width=width,height=height,tags=(uid,contentid),state='hidden')#便笺内容
然后大背景。
注意,默认折叠UI处于折叠状态,而大背景需要根据折叠状态改变大小。
ax1,ay1,ax2,ay2=self.bbox(uid)#大背景
ax1+=5
ay1+=5
ax2-=5
allback=self.create_polygon((ax1,ay1,ax2,ay1,ax2,ay2,ax1,ay2),outline=sep,fill=sep,width=10,tags=uid)
expand=False#当前还没有扩展
折叠逻辑
这里来自于button
的command
绑定。
def do_expand(*e):
nonlocal expand
if expand==False:
expand=True
self.itemconfig(content,state='normal')
self.itemconfig(button[0],text='🔺')
elif expand==True:
expand=False
self.itemconfig(content,state='hidden')
self.itemconfig(button[0],text='🔻')
__size_back()
def __size_back():#调整背景
bx1,by1,bx2,by2=self.bbox(contentid)#大背景
bx1+=5
by1+=5
bx2-=5
self.coords(allback,bx1,by1,bx2,by1,bx2,by2,bx1,by2)
完整代码函数
def add_expander(self,pos:tuple,title='expand content',tfg='black',tbg='#fbfbfb',bg='#f4f4f4',sep='#e5e5e5',width=200,height=200,scrollbar=False,font='微软雅黑 12'):#绘制一个可拓展UI
def do_expand(*e):
nonlocal expand
if expand==False:
expand=True
self.itemconfig(content,state='normal')
self.itemconfig(button[0],text='🔺')
elif expand==True:
expand=False
self.itemconfig(content,state='hidden')
self.itemconfig(button[0],text='🔻')
__size_back()
def __size_back():#调整背景
bx1,by1,bx2,by2=self.bbox(contentid)#大背景
bx1+=5
by1+=5
bx2-=5
self.coords(allback,bx1,by1,bx2,by1,bx2,by2,bx1,by2)
toptext=self.create_text((pos[0]+10,pos[1]+10),text=title,font=font,fill=tfg,width=width-30,anchor='nw')#标题
uid='expander'+str(toptext)
contentid='expander-content'+str(toptext)
#movename='expander-move'+str(toptext)
self.addtag_withtag(uid,toptext)
self.addtag_withtag(contentid,toptext)
tx1,ty1,tx2,ty2=self.bbox(toptext)
if tx2-tx1<width:#判读当前文本宽度
tx2=tx1+width
topback=self.create_polygon((tx1,ty1,tx2,ty1,tx2,ty2,tx1,ty2),outline=tbg,fill=tbg,width=10,tags=(uid,contentid))#标题背景
button=self.add_button2((tx2-2,ty1-0.5),anchor='ne',text='🔻',font=font,fg=tfg,bg=tbg,activebg=bg,command=do_expand)
self.addtag_withtag(uid,button[-1])
self.addtag_withtag(contentid,button[-1])
if not scrollbar:#不使用滚动条,BasicTinUI
ui=BasicTinUI(self,bg=bg)
elif scrollbar:#使用TinUI
ui=TinUI(self,bg=bg)
ux=TinUIXml(ui)
content=self.create_window((tx1,ty2+10),window=ui,anchor='nw',width=width,height=height,tags=(uid,contentid),state='hidden')#便笺内容
ax1,ay1,ax2,ay2=self.bbox(uid)#大背景
ax1+=5
ay1+=5
ax2-=5
allback=self.create_polygon((ax1,ay1,ax2,ay1,ax2,ay2,ax1,ay2),outline=sep,fill=sep,width=10,tags=uid)
expand=False#当前还没有扩展
#调整元素层级关系
self.tkraise(topback)
self.tkraise(toptext)
self.tkraise(button[-1])
return toptext,ui,ux,uid
效果
测试代码
#...
exux=b.add_expander((1200,500))[2]
exux.loadxml('''<tinui><line>
<button2 text='拓展UI框架的按钮'></button2></line>
<line>
<paragraph text='拓展UI框架可以节省布局位置,能够使用TinUIXml为可拓展UI框架编写界面布局。' width='190'></paragraph>
</line>
<line><paragraph text='感觉如何?' width='190'></paragraph></line><line><ratingbar></ratingbar>
</line></tinui>
''')
#...
最终效果
2025-2-4新样式
添加按钮自定义配色参数
github项目
pip下载
pip install tinui
结语
更多想法欢迎到TinUI开源库提交议题。
TinUI有时候的更新可能是“破坏性”的,更新内容见TinUI-ChangeLog。
🔆tkinter创新🔆