tkinter绘制组件(45)——导航栏
tkinter绘制组件(45)——导航栏
- 引言
- 布局
- 函数结构
- 导航栏目
- 处理鼠标信号
- 添加和删除
- 完整代码函数
- 效果
- 测试代码
- 最终效果
- github项目
- pip下载
引言
《汉赛尔和格莱特》吗?有点意思,面包屑。
TinUI中的breadcurmb
期望操作如下:
- 最后一层不可点击;
- 根目录永远存在;
- 返回列表为文本元素的画布id,由编写者自行转为文本。
布局
函数结构
def add_breadcrumb(self,pos:tuple,font='微软雅黑 12',fg='#000000',bg='#ffffff',activefg='#5c5c5c',root='HOME',command=None,anchor='nw'):"""pos::位置fg::文本颜色bg::背景色activefg::响应鼠标文本颜色root::根目录文本command::回调函数,接收层级文本元素列表anchor::整体对齐方向"""
导航栏目
导航栏目很简单,就是一堆导航标题文本,中间使用右箭头文本隔开,只有非最后标题文本可以交互。栈嘛,直接用collections
里的deque
就行,当然,为了方便,右箭头元素也用另一个栈存储。
初始化只需要一个根目录和背景即可。
root = self.create_text(pos, text=root, font=font, fill=fg, anchor='w')
font_size = self.__get_text_size(root)
segeo_font = '{Segoe Fluent Icons}' + font_size
uid = 'breadcrumb' + str(root)
uid_button = uid + 'button'
self.itemconfig(root, tags=(uid,uid_button))bbox = self.bbox(root)
back = self.__ui_polygon(((bbox[0]+2,bbox[1]+2),(bbox[2]-2,bbox[3]-2)),fill=bg,outline=bg,width=9,tags=uid)
self.tkraise(root)stack = collections.deque()
stack.append(root)symstack = collections.deque()_, dy = self.__auto_anchor(uid, pos, anchor)endx = self.bbox(root)[2]
center_line = pos[1] + dy
处理鼠标信号
这个控件的交互很简单,只有鼠标进出和左键单击:
def click(cid):if command == None:returnres = []for i in stack:res.append(i)if i == cid:breakcommand(res)def in_button(cid):self.itemconfig(cid, fill=activefg)def out_button(cid):self.itemconfig(cid, fill=fg)
添加和删除
这里只说添加和删除一个导航标题。
其实需要注意的只有两点:
- 最后的导航标题不可交互。添加后,倒数第二个标题需要响应交互事件;删除后,最后一个标题取消交互;
- 由于
breadcrumb
长度经常变换,因此每次操作后均需要进行对齐。
def add(text):# 添加一个路径元素nonlocal endxsym = self.create_text((endx+2,center_line), text='\uE76C', font=segeo_font, fill=fg, anchor='w', tags=(uid,uid_button))symstack.append(sym)endx = self.bbox(sym)[2]t = self.create_text((endx+2,center_line), text=text, font=font, fill=fg, anchor='w', tags=(uid,uid_button))lt = stack[-1]stack.append(t)bbox = self.bbox(uid_button)self.coords(back, (bbox[0]+2,bbox[1]+2,bbox[2]-2,bbox[1]+2,bbox[2]-2,bbox[3]-2,bbox[0]+2,bbox[3]-2))self.__auto_anchor(uid,pos,anchor)endx = self.bbox(t)[2]self.tag_bind(lt, '<Button-1>', lambda e: click(lt))self.tag_bind(lt, '<Enter>', lambda e: in_button(lt))self.tag_bind(lt, '<Leave>', lambda e: out_button(lt))return tdef delete():# 删除最后一个路径元素nonlocal endxif stack.__len__() > 1:self.delete(stack.pop())self.delete(symstack.pop())bbox = self.bbox(uid_button)self.coords(back, (bbox[0]+2,bbox[1]+2,bbox[2]-2,bbox[1]+2,bbox[2]-2,bbox[3]-2,bbox[0]+2,bbox[3]-2))self.__auto_anchor(uid,pos,anchor)lt = stack[-1]endx = self.bbox(lt)[2]self.tag_unbind(lt, '<Button-1>')self.tag_unbind(lt, '<Enter>')self.tag_unbind(lt, '<Leave>')
完整代码函数
def add_breadcrumb(self,pos:tuple,font='微软雅黑 12',fg='#000000',bg='#ffffff',activefg='#5c5c5c',root='HOME',command=None,anchor='nw'):# 绘制面包屑导航组件def click(cid):if command == None:returnres = []for i in stack:res.append(i)if i == cid:breakcommand(res)def in_button(cid):self.itemconfig(cid, fill=activefg)def out_button(cid):self.itemconfig(cid, fill=fg)def get():# 获取当前路径元素return list(stack)def add(text):# 添加一个路径元素nonlocal endxsym = self.create_text((endx+2,center_line), text='\uE76C', font=segeo_font, fill=fg, anchor='w', tags=(uid,uid_button))symstack.append(sym)endx = self.bbox(sym)[2]t = self.create_text((endx+2,center_line), text=text, font=font, fill=fg, anchor='w', tags=(uid,uid_button))lt = stack[-1]stack.append(t)bbox = self.bbox(uid_button)self.coords(back, (bbox[0]+2,bbox[1]+2,bbox[2]-2,bbox[1]+2,bbox[2]-2,bbox[3]-2,bbox[0]+2,bbox[3]-2))self.__auto_anchor(uid,pos,anchor)endx = self.bbox(t)[2]self.tag_bind(lt, '<Button-1>', lambda e: click(lt))self.tag_bind(lt, '<Enter>', lambda e: in_button(lt))self.tag_bind(lt, '<Leave>', lambda e: out_button(lt))return tdef delete():# 删除最后一个路径元素nonlocal endxif stack.__len__() > 1:self.delete(stack.pop())self.delete(symstack.pop())bbox = self.bbox(uid_button)self.coords(back, (bbox[0]+2,bbox[1]+2,bbox[2]-2,bbox[1]+2,bbox[2]-2,bbox[3]-2,bbox[0]+2,bbox[3]-2))self.__auto_anchor(uid,pos,anchor)lt = stack[-1]endx = self.bbox(lt)[2]self.tag_unbind(lt, '<Button-1>')self.tag_unbind(lt, '<Enter>')self.tag_unbind(lt, '<Leave>')def delete_to(cid):nonlocal endxwhile stack.__len__() > 1 and stack[-1] != cid:self.delete(stack.pop())self.delete(symstack.pop())bbox = self.bbox(uid_button)self.coords(back, (bbox[0]+2,bbox[1]+2,bbox[2]-2,bbox[1]+2,bbox[2]-2,bbox[3]-2,bbox[0]+2,bbox[3]-2))self.__auto_anchor(uid,pos,anchor)lt = stack[-1]endx = self.bbox(lt)[2]self.tag_unbind(lt, '<Button-1>')self.tag_unbind(lt, '<Enter>')self.tag_unbind(lt, '<Leave>')root = self.create_text(pos, text=root, font=font, fill=fg, anchor='w')font_size = self.__get_text_size(root)segeo_font = '{Segoe Fluent Icons}' + font_sizeuid = 'breadcrumb' + str(root)uid_button = uid + 'button'self.itemconfig(root, tags=(uid,uid_button))bbox = self.bbox(root)back = self.__ui_polygon(((bbox[0]+2,bbox[1]+2),(bbox[2]-2,bbox[3]-2)),fill=bg,outline=bg,width=9,tags=uid)self.tkraise(root)stack = collections.deque()stack.append(root)symstack = collections.deque()_, dy = self.__auto_anchor(uid, pos, anchor)endx = self.bbox(root)[2]center_line = pos[1] + dyfuncs = FuncList(4)funcs.get = getfuncs.add = addfuncs.delete = deletefuncs.delete_to = delete_toreturn root, back, funcs, uid
效果
测试代码
bc = b.add_breadcrumb((1500,350),anchor='n',command=print)[-2]
for i in range(1,4):bc.add(f'item{i}')
最终效果
github项目
TinUI的github项目地址
pip下载
pip install tinui