Python Tkinter如何检测鼠标在按钮外部释放并避免异常变色
问题根因
高亮变色逻辑绑定在<Button-1>(鼠标按下事件)上,只要鼠标在按钮上按下就立刻触发变色,但Tkinter按钮原生command回调的触发规则为按钮范围内按下+按钮范围内松开才会执行,二者触发逻辑不一致就出现了异常高亮的问题。
修复步骤
- 把变色触发事件从按下改为
<ButtonRelease-1>(鼠标松开事件),同时增加鼠标位置校验,仅当松开时指针仍在按钮范围内才执行高亮逻辑 - 修复原代码中的笔误:未声明的
B1ButtonCls改为自定义的TypeButton、不存在的容器self.frame_1改为self.frame、调整回调函数参数兼容事件绑定要求
修复后完整可运行代码
from tkinter import * class TypeButton(Button): def __init__(self, parent, *args, **kwargs): kwargs = {'font':('Calibri',9,'bold'), 'bg': '#11161d', 'fg':'white', 'width':10, 'bd':0, 'activebackground':'#bdfe04', **kwargs} super().__init__(parent, *args, **kwargs) class Example(Frame): def __init__(self,parent, *args, **kwargs): super().__init__(parent, *args, **kwargs) self.frame = Frame(self, bg='#11161d') self.frame.grid(padx=(10,10), pady=(6,6)) self.container1 = None self.creator_buttons() self.bind_all("<B1-Motion>", self.callback) def creator_buttons(self): mobiles = [['Frog', 'Fox', 'Boomer', 'Ice', 'J.d', 'Grub', 'Lightning', 'Aduka', 'Knight', 'Kalsiddon', 'Mage'], ['Randomizer', 'Jolteon', 'Turtle', 'Armor', 'A.sate', 'Raon', 'Trico', 'Nak', 'Bigfoot', 'Barney', 'Dragon']] self.mobiles2 = ['Fox','Knight','Jolteon','Barney','Dragon'] self.buttons22 = [] for index1, mobil in enumerate(mobiles): for index2, texto in enumerate(mobil): btn = TypeButton(self.frame, text=texto, command= self.callback) n1 = 5 if index2 == 0 else 0 n2 = 5 if index2 == 10 else 0 btn.grid(column=index2 , row=index1 , pady=3, padx=(n1,n2)) btn.bind("<Enter>", self.enter_mouse) btn.bind("<Leave>", self.leave_mouse) # 把按下事件改成松开事件 btn.bind("<ButtonRelease-1>", self.clic_mouse) if texto in self.mobiles2: btn.config(fg='yellow') self.buttons22.append(btn) def enter_mouse(self, event): widget1 = event.widget if not widget1.cget('bg') == '#bdfe04': widget1.config(bg="#24364a") def leave_mouse(self, event): if not event.widget.cget('bg') == '#bdfe04': event.widget.config(bg='#11161d') def clic_mouse(self, event): widget1 = event.widget # 新增校验:仅当松开时鼠标仍在按钮范围内才触发变色 if 0 <= event.x < widget1.winfo_width() and 0 <= event.y < widget1.winfo_height(): widget1.config(bg='#bdfe04', fg='black') if self.container1 is not None and self.container1 != widget1: if self.container1.cget('text') in self.mobiles2: self.container1.config (bg='#11161d', fg='yellow') else: self.container1.config (bg='#11161d', fg='white') self.container1 = widget1 # 增加*args兼容事件绑定的参数传入 def callback(self, *args): print('Closed') root = Tk() app = Example(root).pack() root.mainloop()
内容的提问来源于stack exchange,提问作者Benjamin
相关产品推荐
相关产品推荐

