如何将父控件的事件处理传播到子控件?
import tkinter as tk
root = tk.Tk()
frame_top = tk.Frame(root, bg="lightyellow")
frame_top.pack(fill="both", expand=True)
label_top_1 = tk.Label(frame_top, text="Label", fg="white", bg="darkred")
label_top_1.pack(padx=50, pady=20)
label_top_2 = tk.Label(frame_top, text="Label", fg="white", bg="darkred")
label_top_2.pack(padx=50, pady=20)
frame_bottom = tk.Frame(root, bg="lightblue")
frame_bottom.pack(fill="both", expand=True)
label_bottom_1 = tk.Label(frame_bottom, text="Label", fg="white", bg="darkred")
label_bottom_1.pack(padx=50, pady=20)
label_bottom_2 = tk.Label(frame_bottom, text="Label", fg="white", bg="darkred")
label_bottom_2.pack(padx=50, pady=20)
root.mainloop()

添加鼠标点击事件处理:
def frame_top_onclick(event):
print("top frame clicked")
def frame_bottom_onclick(event):
print("bottom frame clicked")
frame_top.bind("<Button-1>", frame_top_onclick, add="+")
frame_bottom.bind("<Button-1>", frame_bottom_onclick, add="+")
它在点到框架本身时能工作。但如果点到其中一个标签,什么也不会发生。
当然,我也可以为每个子控件添加事件处理:
label_top_1.bind("<Button-1>", frame_top_onclick, add="+")
label_top_2.bind("<Button-1>", frame_top_onclick, add="+")
label_bottom_1.bind("<Button-1>", frame_bottom_onclick, add="+")
label_bottom_2.bind("<Button-1>", frame_bottom_onclick, add="+")
但这显得不必要地复杂,尤其是某些子控件只有在运行时才会被添加。
是否有内置的方法,可以将事件处理从父控件传递到它的子控件?
解决方案
除了 bind 之外,还有 bind_all:
frame_top.bind_all("<Button-1>", frame_top_onclick, add="+")
frame_bottom.bind_all("<Button-1>", frame_bottom_onclick, add="+")
然而,这会对所有控件绑定指定的事件,毫不区分地触发。点击框架或任意一个标签都会触发这两个处理程序。不过,可以在中间加一个筛选器来解决,这个筛选器会检查触发控件是否确实是相应框架的子控件:
def bind_children(parent, event_name, callback, include_parent=True):
def _callback(event):
widget = event.widget
if not include_parent:
widget = widget.master
while widget:
if widget == parent:
return callback(event)
widget = widget.master
return parent.bind_all(event_name, _callback, add="+")
bind_children(frame_top, "<Button-1>", frame_top_onclick)
bind_children(frame_bottom, "<Button-1>", frame_bottom_onclick)
通过设置 include_parent=False,你甚至可以为一个控件的所有子控件创建事件处理程序,而不把父控件本身作为触发对象。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。