如何让Tkinter的Toplevel窗口不触发父组件的FocusOut事件
解决方案:过滤应用内窗口切换的FocusOut事件
可以实现需求。问题核心在于:即便将Toplevel的master设为Frame,它仍是独立的顶层窗口,当焦点在同一应用的不同顶层窗口间切换时,原Frame的FocusOut事件仍会被触发。解决思路是在事件处理函数中判断新焦点是否属于当前应用的窗口,若是则跳过事件执行。
修改后的代码如下:
from tkinter import Tk, Frame, Entry, Toplevel def focus_out(event): # 通过点击位置反查新焦点所在的组件 new_focus_widget = event.widget.winfo_containing(event.x_root, event.y_root) if new_focus_widget: # 获取该组件所属的顶层窗口 target_toplevel = new_focus_widget.winfo_toplevel() # 检查顶层窗口是否属于当前应用的窗口 if target_toplevel in (root, t): return # 仅当焦点离开当前应用时执行操作 print("focus out") root = Tk() root.title("Main") root.geometry("400x400") frame = Frame(root) frame.pack() frame.bind("<FocusOut>", focus_out) e = Entry(frame) e.pack() t = Toplevel(frame) t.geometry("400x400") t.title("top level") Entry(t).pack() root.mainloop()
关键逻辑说明
winfo_containing(event.x_root, event.y_root):利用鼠标点击的屏幕坐标,定位新获得焦点的组件。winfo_toplevel():获取组件所属的顶层窗口(Tk或Toplevel实例)。- 若目标顶层窗口是当前应用内的窗口(
root或自定义的Toplevel),则直接返回,不执行后续事件逻辑。
调整后,从主窗口Entry切换到Toplevel窗口的Entry时,不会触发Frame的FocusOut事件;只有当焦点切换到其他应用窗口时,才会执行事件代码。
内容的提问来源于stack exchange,提问作者Raphael
相关产品推荐
相关产品推荐

