尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

tkinter绘制组件(38)——状态开关按钮

tkinter绘制组件(38)——状态开关按钮 tkinter绘制组件38——状态开关按钮引言布局函数结构按钮主体渐变色处理颜色处理基础渐变色列表形成列表样式绑定完整函数代码效果测试代码最终效果2025-2-5修复2026-8-16 样式更新github项目pip下载结语引言TinUI里的状态开关按钮togglebutton和开关onoff一样都是用来显示并操作两种对立状态的交互控件。在很多UI库中这两个控件均由按钮派生出来。开关类控件提供了即时状态改变响应的接口开关控件多用于设置界面状态开关按钮则多用于应用运行中的状态更改。布局函数结构defadd_togglebutton(self,pos:tuple,text:str,fg#1b1b1b,bg#fbfbfb,line#CCCCCC,linew1,activefg#f3f4fd,activebg#3041d8,activeline#5360de,font(微软雅黑,12),commandNone,anchornw):#绘制状态开关按钮 - pos::位置 - text::文本 - fg::文本颜色 - bg::背景色 - line::边框颜色 - linew::边框宽度 - activefg::开启状态文本颜色 - activebg::开启状态背景色 - activeline::开启状态边框颜色 - font::字体 - command::响应函数接受一个参数True开启False关闭 - anchor::对齐方向 按钮主体参考WinUI3中的状态开关按钮按钮的主体使用TinUI中的圆角按钮button2在此基础上进行功能修改#...buttonself.create_text(pos,texttext,fillfg,fontfont,anchoranchor)uidtogglebuttonstr(button)self.itemconfig(button,tagsuid)x1,y1,x2,y2self.bbox(button)linew-1outline_t(x1-linew,y1-linew,x2linew,y1-linew,x2linew,y2linew,x1-linew,y2linew)outlineself.create_polygon(outline_t,width9,tagsuid,fillline,outlineline)back_t(x1,y1,x2,y1,x2,y2,x1,y2)backself.create_polygon(back_t,width7,tagsuid,fillbg,outlinebg)self.tag_bind(button,Button-1,on_click)#self.tag_bind(button,Enter,in_button)#self.tag_bind(button,Leave,out_button)self.tag_bind(back,Button-1,on_click)#self.tag_bind(back,Enter,in_button)#self.tag_bind(back,Leave,out_button)self.tkraise(button)funcsFuncList(3)funcs.change_commandchange_command funcs.disabledisable funcs.activeactive#...整个绘制过程基本copy了button2的代码但是除了一些小修改以外就是去除了对于鼠标进出的响应过程被注释掉的代码。为了避免添加过多参数同时方便编写者管理按钮样式将激活时的颜色作为状态开启的提示色。渐变色处理这是togglebutton创建的一个重点也是唯一值得讲一讲的。TinUI中使用渐变色作为togglebutton的过渡动画。因为这一段代码是我突发兴致决定的所以肯定由比较繁琐的地方往后或许会修改也希望指正。颜色处理基础渐变色过程由十进制方式计算而tkinterTcl/Tk的颜色模式采用的是十六进制字符串很有想法做个微操def__rgb2num(rgb):#tkinter颜色类型转十进制rgbreturnint(rgb[1:3],16),int(rgb[3:5],16),int(rgb[5:],16)def__num2rgb(hexs:tuple):#十进制rgb转tkinter颜色类型co#foriinhexs:costr(hex(i))[2:]returnco渐变色列表为了不让动画过于耗时使用两个列表存储渐变颜色25个过渡颜色而不是临时计算一个列表是从关闭状态到激活状态的颜色变化另一个就是倒序。因此只需要写一个正序颜色列表的计算式就行了。思路也十分清晰简单将始末颜色转为十进制方便计算。分别计算RGB差值末减初。循环25遍算上初始值是26遍每次计算颜色变化量t。具体代码如下defget_color_change(st,ed):colors_list[]#起始和终止颜色十进制rgba1,a2,a3__rgb2num(st)b1,b2,b3__rgb2num(ed)#两颜色差值r,g,b(b1-a1),(b2-a2),(b3-a3)foriinrange(26):ti/25rgb(int(a1r*t),int(a2g*t),int(a3b*t))colors_list.append(__num2rgb(rgb))returncolors_list其中的r,g,b是颜色差值ti/25就是在计算颜色变化量也就是渐变到哪一步的指示。通过[r|g|b] * t就可以得到这一步颜色的具体变化值。之后可能把这个渐变色列表生成方法作为TinUI的通用函数具体看其它控件使用需要。形成列表这一步就简单了。#...#处理渐变色colors.append(get_color_change(fg,activefg))#文本颜色colors.append(get_color_change(bg,activebg))#背景颜色#re_colors 反向颜色列表re_colors[colors[0][::-1],colors[1][::-1]]nowcolorscolors样式绑定这里要注意我们之前只是创建了渐变颜色列表而已动画部分还没完成。因为控件的不同状态对应的渐变顺序不一样因此每当按钮状态改变时要重新指定动画颜色列表这个操作放在on_click中执行。defon_click(event):nonlocalstateifstateFalse:stateTrueself.itemconfig(outline,fillactiveline,outlineactiveline)change_color(0,2)else:stateFalseself.itemconfig(outline,fillline,outlineline)change_color(0,1)ifcommand!None:command(state)里面提到的change_color就是变化颜色函数通过tkinter计时器进行函数循环间隔时间是0.005秒完成后改变指向的颜色列表。defchange_color(t,change:int):#变化颜色#change:: 1colors, 2re_colorsnonlocalnowcolorsift25:self.itemconfig(back,fillnowcolors[1][t],outlinenowcolors[1][t])self.itemconfig(button,fillnowcolors[0][t])self.after(5,lambda:change_color(t1,change))else:ifchange1:nowcolorscolorselifchange2:nowcolorsre_colors完整函数代码defadd_togglebutton(self,pos:tuple,text:str,fg#1b1b1b,bg#fbfbfb,line#CCCCCC,linew1,activefg#f3f4fd,activebg#3041d8,activeline#5360de,font(微软雅黑,12),commandNone,anchornw):#绘制状态开关按钮defin_button(event):pass#状态开关按钮当前不再对鼠标进入和离开进行响应defout_button(event):passdefon_click(event):nonlocalstateifstateFalse:stateTrueself.itemconfig(outline,fillactiveline,outlineactiveline)change_color(0,2)else:stateFalseself.itemconfig(outline,fillline,outlineline)change_color(0,1)ifcommand!None:command(state)defchange_color(t,change:int):#变化颜色#change:: 1colors, 2re_colorsnonlocalnowcolorsift25:self.itemconfig(back,fillnowcolors[1][t],outlinenowcolors[1][t])self.itemconfig(button,fillnowcolors[0][t])self.after(5,lambda:change_color(t1,change))else:ifchange1:nowcolorscolorselifchange2:nowcolorsre_colorsdefchange_command(new_func):nonlocalcommand commandnew_funcdefdisable(fg#9d9d9d,bg#f5f5f5):ifstateFalse:#区分当前状态进行禁用配色self.itemconfig(button,statedisable,fillfg)self.itemconfig(back,statedisable,disabledfillbg)else:self.itemconfig(button,statedisable,fillbg)self.itemconfig(back,statedisable,disabledfillfg)defactive():self.itemconfig(button,statenormal)self.itemconfig(back,statenormal)out_button(None)def__rgb2num(rgb):#tkinter颜色类型转十进制rgbreturnint(rgb[1:3],16),int(rgb[3:5],16),int(rgb[5:],16)def__num2rgb(hexs:tuple):#十进制rgb转tkinter颜色类型co#foriinhexs:costr(hex(i))[2:]returncodefget_color_change(st,ed):colors_list[]#起始和终止颜色十进制rgba1,a2,a3__rgb2num(st)b1,b2,b3__rgb2num(ed)#两颜色差值r,g,b(b1-a1),(b2-a2),(b3-a3)foriinrange(26):ti/25rgb(int(a1r*t),int(a2g*t),int(a3b*t))colors_list.append(__num2rgb(rgb))returncolors_list stateFalse#off:False on:Truecolors[]#渐变色颜色列表25个off-on[[文本颜色,...],[背景色,...]]buttonself.create_text(pos,texttext,fillfg,fontfont,anchoranchor)uidtogglebuttonstr(button)self.itemconfig(button,tagsuid)x1,y1,x2,y2self.bbox(button)linew-1outline_t(x1-linew,y1-linew,x2linew,y1-linew,x2linew,y2linew,x1-linew,y2linew)outlineself.create_polygon(outline_t,width9,tagsuid,fillline,outlineline)back_t(x1,y1,x2,y1,x2,y2,x1,y2)backself.create_polygon(back_t,width7,tagsuid,fillbg,outlinebg)self.tag_bind(button,Button-1,on_click)#self.tag_bind(button,Enter,in_button)#self.tag_bind(button,Leave,out_button)self.tag_bind(back,Button-1,on_click)#self.tag_bind(back,Enter,in_button)#self.tag_bind(back,Leave,out_button)self.tkraise(button)funcsFuncList(3)funcs.change_commandchange_command funcs.disabledisable funcs.activeactive#处理渐变色colors.append(get_color_change(fg,activefg))#文本颜色colors.append(get_color_change(bg,activebg))#背景颜色#re_colors 反向颜色列表re_colors[colors[0][::-1],colors[1][::-1]]nowcolorscolorsreturnbutton,back,outline,funcs,uid效果测试代码deftest13(state):ifstate:b.itemconfig(tgbutton,text状态开关按钮开启)else:b.itemconfig(tgbutton,text状态开关按钮关闭)if__name____main__:tgbuttonb.add_togglebutton((1200,230),text状态开关按钮关闭,commandtest13)[0]最终效果2025-2-5修复修复渐变色的计算错误包括超出255的部分转化十六进制后只有个位数进行补位2026-8-16 样式更新添加了响应鼠标进入的样式表破坏性更新部分参数重命名github项目TinUI的github项目地址pip下载pipinstalltinui结语TinUI4可能会时不时加一些莫名其妙的控件而基础的应用功能基本不会改变但还是会偶尔更新的。tkinter创新
返回列表