如何实现点击任意Tkinter按钮时多个按钮同步显示按下状态?
问题原因及解决方案
问题根源
你的代码运行后只有btn4有反应,是两个问题导致的:
- 连续调用
event_generate生成按压、释放事件的间隔过短,Tkinter事件循环来不及渲染前三个按钮的按压动画,就执行了后续按钮的操作,最终只有最后处理的btn4的动画能正常显示 - 反复修改按钮的command绑定属于冗余操作,额外增加了逻辑复杂度
修正后可直接运行的代码
from tkinter import * from tkinter import ttk class one_for_all: def __init__(self): self.root = Tk() self.root.title("One For All, All For One") self.frame = ttk.Frame(self.root, padding="3 3 12 12") self.frame.grid(row=0, column=0) self.root.rowconfigure(0, weight=1) self.root.columnconfigure(0, weight=1) # 把所有按钮存到列表里统一管理,避免重复写逻辑 self.buttons = [ ttk.Button(self.frame, text="btn1", command=lambda : self.push_all()), ttk.Button(self.frame, text="btn2", command=lambda : self.push_all()), ttk.Button(self.frame, text="btn3", command=lambda : self.push_all()), ttk.Button(self.frame, text="btn4", command=lambda : self.push_all()) ] # 批量布局按钮 for idx, btn in enumerate(self.buttons): row = idx // 2 col = idx % 2 btn.grid(row=row, column=col, sticky="nsew") for child in self.frame.winfo_children(): child.grid_configure(padx=5, pady=5) def push_all(self): # 先把所有按钮设为按压状态 for btn in self.buttons: btn.state(['pressed']) # 100ms后恢复普通状态,保证按压效果能被看到 self.root.after(100, lambda: [btn.state(['!pressed']) for btn in self.buttons]) def mainloop(self): self.root.mainloop() if __name__ == "__main__": one_for_all().mainloop()
核心改动说明
- 用列表统一管理所有按钮,省去了逐一对每个按钮写判断逻辑的重复操作,后续要加按钮只要往列表里加即可
- 去掉了冗余的事件生成、command修改逻辑,直接通过ttk按钮的
state属性控制按压状态,性能更好逻辑更清晰 - 用Tkinter内置的
after方法设置延迟,保证所有按钮的按压状态都能被正常渲染后再恢复,同步效果一致
内容的提问来源于stack exchange,提问作者Kunal Sharma
相关产品推荐
相关产品推荐

