You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:01:20