☰
tkinter绘制组件(46)——分段按钮
2026/10/4 9:46:18 网站建设 项目流程

tkinter绘制组件(46)——分段按钮

  • 引言
  • 布局
    • 函数结构
    • 所有元素
    • 文本布局
    • 转到指定位置
    • 处理鼠标信号
    • 完整代码函数
  • 效果
    • 2026-10-3 样式更新
  • github项目
  • pip下载

引言

分段按钮可以通过按钮的形式,对同目的功能进行分类。


布局

函数结构

defadd_segmentbutton(self,pos:tuple,fg='#191919',bg='#EDEDED',activefg='#181818',activebg='#E5E5E5',onbg='#FAFAFA',line='#E5E5E5',sign='#3041d8',font='微软雅黑 12',content=('A','B','C'),command=None,anchor='nw'):""" pos::位置 fg::文本颜色 bg::背景色 activefg::响应时文本颜色 activebg::响应时背景色 onbg::选中时背景色 line::边框颜色 sign::提示符颜色 font::字体 content::内容 command::回调函数,必须接受一个参数,选中的按钮文本 anchor::对齐方向 """

所有元素

由于分段按钮有多个部件构成,且现在TinUI已经实现了完善的布局计算功能,所以先将所有需要的元素全部创建出来。

index=-1outline=self.__ui_polygon(((0,0),(0,0)),fill=line,outline=line,width=9)uid=TinUIString(f'segmentbutton-{outline}')buttonid=f'{uid}-button'self.itemconfig(outline,tags=uid)back=self.__ui_polygon(((0,0),(0,0)),fill=bg,outline=bg,width=9,tags=uid)button=self.__ui_polygon(((0,0),(0,0)),fill='',outline='',width=9,tags=uid)button2=self.__ui_polygon(((0,0),(0,0)),fill=onbg,outline=onbg,width=9,tags=uid)line=self.create_line((0,0,0,0),fill=sign,width=3,tags=uid,capstyle='round',state='hidden')self.itemconfig(button2,state='hidden')maxwidth=0texts=[]foriincontent:text=self.create_text((0,0),text=i,font=font,fill=fg,anchor='n',tags=(uid,buttonid))texts.append(text)bbox=self.bbox(text)maxwidth=max(maxwidth,bbox[2]-bbox[0])self.tag_bind(text,'<Enter>',lambdae,text=text:mouse_in(text))self.tag_bind(text,'<Leave>',lambdae,text=text:self.itemconfig(text,fill=fg))self.tag_bind(text,'<Button-1>',lambdae,text=text:__click(text))

这里面分别是背景、边框、按钮文本、选择元素、选定元素、提示线。

文本布局

分段按钮采用水平等宽布局,因此上面的代码中记录了maxwidth,各按钮文本居中布局。

endx=maxwidth/2foriintexts:self.coords(i,endx,0)endx+=maxwidth+10bbox=self.bbox(buttonid)width=(maxwidth+10)*content.__len__()-10coord=(0,bbox[1],width,bbox[1],width,bbox[3],0,bbox[3])self.coords(back,coord)coord=(-1,bbox[1]-1,width+1,bbox[1]-1,width+1,bbox[3]+1,-1,bbox[3]+1)self.coords(outline,coord)

转到指定位置

self.__auto_anchor(uid,pos,anchor)

处理鼠标信号

由于选定和选择会同时存在,因此这里使用了两个圆角矩形元素来响应鼠标事件。当鼠标选择文本时,由button响应,选定时由button2响应。鼠标的离开由整个控件告知button。

defmouse_in(cid):bbox=self.bbox(cid)centerx=(bbox[0]+bbox[2])/2halfwidth=maxwidth/2x1=centerx-halfwidth x2=centerx+halfwidth coord=(x1,bbox[1],x2,bbox[1],x2,bbox[3],x1,bbox[3])self.coords(button,coord)self.itemconfig(button,fill=activebg,outline=activebg)self.itemconfig(cid,fill=activefg)defon_leave(e):self.itemconfig(button,fill='',outline='')def__click(cid):nonlocalindexifindex==-1:self.itemconfig(button2,state='normal')self.itemconfig(line,state='normal')ifcid==index:returnindex=cid bbox=self.bbox(cid)centerx=(bbox[0]+bbox[2])//2halfwidth=maxwidth/2x1=centerx-halfwidth x2=centerx+halfwidth coord=(x1,bbox[1],x2,bbox[1],x2,bbox[3],x1,bbox[3])self.coords(button2,coord)self.coords(line,((bbox[0]+bbox[2])/2-maxwidth/4,bbox[3]+2,(bbox[0]+bbox[2])/2+maxwidth/4,bbox[3]+2))ifcommand:command(self.itemcget(cid,'text'))

完整代码函数

defadd_segmentbutton(self,pos:tuple,fg='#191919',bg='#EDEDED',activefg='#181818',activebg='#E5E5E5',onbg='#FAFAFA',line='#E5E5E5',sign='#3041d8',font='微软雅黑 12',content=('A','B','C'),command=None,anchor='nw'):# 绘制一个选项按钮defmouse_in(cid):bbox=self.bbox(cid)centerx=(bbox[0]+bbox[2])/2halfwidth=maxwidth/2x1=centerx-halfwidth x2=centerx+halfwidth coord=(x1,bbox[1],x2,bbox[1],x2,bbox[3],x1,bbox[3])self.coords(button,coord)self.itemconfig(button,fill=activebg,outline=activebg)self.itemconfig(cid,fill=activefg)defon_leave(e):self.itemconfig(button,fill='',outline='')def__click(cid):nonlocalindexifindex==-1:self.itemconfig(button2,state='normal')self.itemconfig(line,state='normal')ifcid==index:returnindex=cid bbox=self.bbox(cid)centerx=(bbox[0]+bbox[2])//2halfwidth=maxwidth/2x1=centerx-halfwidth x2=centerx+halfwidth coord=(x1,bbox[1],x2,bbox[1],x2,bbox[3],x1,bbox[3])self.coords(button2,coord)self.coords(line,((bbox[0]+bbox[2])/2-maxwidth/4,bbox[3]+2,(bbox[0]+bbox[2])/2+maxwidth/4,bbox[3]+2))ifcommand:command(self.itemcget(cid,'text'))index=-1outline=self.__ui_polygon(((0,0),(0,0)),fill=line,outline=line,width=9)uid=TinUIString(f'segmentbutton-{outline}')buttonid=f'{uid}-button'self.itemconfig(outline,tags=uid)back=self.__ui_polygon(((0,0),(0,0)),fill=bg,outline=bg,width=9,tags=uid)button=self.__ui_polygon(((0,0),(0,0)),fill='',outline='',width=9,tags=uid)button2=self.__ui_polygon(((0,0),(0,0)),fill=onbg,outline=onbg,width=9,tags=uid)line=self.create_line((0,0,0,0),fill=sign,width=3,tags=uid,capstyle='round',state='hidden')self.itemconfig(button2,state='hidden')maxwidth=0texts=[]foriincontent:text=self.create_text((0,0),text=i,font=font,fill=fg,anchor='n',tags=(uid,buttonid))texts.append(text)bbox=self.bbox(text)maxwidth=max(maxwidth,bbox[2]-bbox[0])self.tag_bind(text,'<Enter>',lambdae,text=text:mouse_in(text))self.tag_bind(text,'<Leave>',lambdae,text=text:self.itemconfig(text,fill=fg))self.tag_bind(text,'<Button-1>',lambdae,text=text:__click(text))endx=maxwidth/2foriintexts:self.coords(i,endx,0)endx+=maxwidth+10bbox=self.bbox(buttonid)width=(maxwidth+10)*content.__len__()-10coord=(0,bbox[1],width,bbox[1],width,bbox[3],0,bbox[3])self.coords(back,coord)coord=(-1,bbox[1]-1,width+1,bbox[1]-1,width+1,bbox[3]+1,-1,bbox[3]+1)self.coords(outline,coord)self.tag_bind(uid,'<Leave>',on_leave)self.__auto_anchor(uid,pos,anchor)deltexts,endx,coord,bbox uid.layout=lambdax1,y1,x2,y2,expand=False:self.__auto_layout(uid,(x1,y1,x2,y2),anchor)returnback,outline,button,button2,line,uid

效果

暗黑样式:

2026-10-3 样式更新

添加了线性过渡动画。


github项目

TinUI的github项目地址

pip下载

pipinstalltinui

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询