如何在Tkinter程序的多个Toplevel窗口间切换焦点?
解决Tkinter多窗口快捷键仅最后一个窗口响应的问题
问题根源在于你使用了bind_all方法——这个方法会把快捷键绑定到整个Tkinter应用的所有组件上,每次创建新窗口时,新的绑定会覆盖之前的设置,导致最后创建的窗口的menu方法成为全局唯一的响应函数,不管哪个窗口有焦点,都会调用它。
修复步骤
- 把
bind_all替换为bind,仅将快捷键绑定到当前窗口的顶级组件(self.top),这样只有当该窗口获得焦点时,快捷键才会触发对应的menu方法。 - 移除冗余的
focus_force()调用,仅在窗口初始化时调用focus_set()确保窗口能正常获取焦点,避免强制抢焦点的无效操作。
修复后的代码
import tkinter as tk from tkinter import ttk class win: number = 0 def __init__(self): win.number += 1 self.number = win.number self.top = tk.Toplevel() self.top.protocol("WM_DELETE_WINDOW", lambda: self.close_root()) # 用bind替代bind_all,仅绑定到当前窗口 self.top.bind("<Control-o>", lambda event : self.menu()) self.file_menu_button = ttk.Menubutton(self.top, text="File menu of top" + str(self.number)) self.file_menu_button.grid() self.file_menu = tk.Menu(self.file_menu_button) self.file_menu.add_command(label="Open", accelerator="Ctrl+o", command=self.menu) self.file_menu_button.configure(menu=self.file_menu) self.canvas = tk.Canvas(self.top, width=400, height=200) self.canvas.grid() # 窗口初始化时设置焦点,移除重复的FocusIn绑定 self.top.focus_set() def close_root(self): root.quit() def menu(self): print("menu" + str(self.number) + " clicked") root = tk.Tk() root.withdraw() win1 = win() win2 = win() root.mainloop()
额外说明
accelerator参数只是在菜单上显示快捷键提示,不会自动完成事件绑定,必须手动通过bind或bind_all实现实际的快捷键功能。- 点击任意窗口使其获得焦点后,按下
Ctrl+O,就会触发该窗口对应的menu方法,输出对应的窗口编号。
内容的提问来源于stack exchange,提问作者Matthias Schweikart
相关产品推荐
相关产品推荐

