Mon*_*yer 6 python events tkinter
在下面的块中,单击a_frame会触发事件处理程序on_frame_click,但是单击a_label哪个子事件a_frame不会触发事件处理程序.有没有办法强制a_frame陷阱和处理源自它的孩子的事件(最好不必直接向孩子们添加处理程序)?我使用的是Python 3.2.3.
import tkinter
def on_frame_click(e):
print("frame clicked")
tk = tkinter.Tk()
a_frame = tkinter.Frame(tk, bg="red", padx=20, pady=20)
a_label = tkinter.Label(a_frame, text="A Label")
a_frame.pack()
a_label.pack()
tk.protocol("WM_DELETE_WINDOW", tk.destroy)
a_frame.bind("<Button>", on_frame_click)
tk.mainloop()
Run Code Online (Sandbox Code Playgroud)
Bry*_*ley 14
是的,你可以做你想做的事,但这需要一些工作.并不是它不受支持,只是因为它实际上很少需要这样的东西所以它不是默认行为.
TL; DR - 研究"tkinter绑定标签"
Tkinter事件模型包括" 绑定标记 " 的概念.这是与每个小部件关联的标签列表.在窗口小部件上收到事件时,将检查每个绑定标记以查看它是否具有该事件的绑定.如果是,则调用处理程序.如果没有,它继续.如果处理程序返回"break",则链断开,不再考虑标记.
默认情况下,窗口小部件的绑定标记是窗口小部件本身,窗口小部件类,窗口小部件所在的顶层窗口的标记,最后是特殊标记"all".但是,您可以在其中放置所需的任何标签,并且可以更改顺序.
所有这些的实际结果?您可以将自己的唯一标记添加到每个窗口小部件,然后将单个绑定添加到将由所有窗口小部件处理的标记.这是一个例子,使用你的代码作为起点(我添加了一个按钮小部件,以显示这不是一个特殊的框架和标签):
import Tkinter as tkinter
def on_frame_click(e):
print("frame clicked")
def retag(tag, *args):
'''Add the given tag as the first bindtag for every widget passed in'''
for widget in args:
widget.bindtags((tag,) + widget.bindtags())
tk = tkinter.Tk()
a_frame = tkinter.Frame(tk, bg="red", padx=20, pady=20)
a_label = tkinter.Label(a_frame, text="A Label")
a_button = tkinter.Button(a_frame, text="click me!")
a_frame.pack()
a_label.pack()
a_button.pack()
tk.protocol("WM_DELETE_WINDOW", tk.destroy)
retag("special", a_frame, a_label, a_button)
tk.bind_class("special", "<Button>", on_frame_click)
tk.mainloop()
Run Code Online (Sandbox Code Playgroud)
有关bindtags的更多信息,您可能会对我在Tkinter Text小部件中绑定自我事件的问题的答案感兴趣,因为它将被Text小部件绑定?.答案解决了与此处不同的问题,但它显示了使用绑定标记解决实际问题的另一个例子.
我似乎找不到自动绑定到子小部件的直接方法(尽管有绑定到整个小部件类和应用程序中的所有小部件的方法),但这样的事情很容易。
def bind_tree(widget, event, callback, add=''):
"Binds an event to a widget and all its descendants."
widget.bind(event, callback, add)
for child in widget.children.values():
bind_tree(child, event, callback, replace_callback)
Run Code Online (Sandbox Code Playgroud)
只是想到了这一点,但是您也可以将大小为 的透明小部件a_frame作为其子项放在所有内容的顶部a_frame并将<Button>事件绑定到该小部件,然后您可以在回调中引用a_framease.widget.master以便在必要时使其可重用。那可能会做你想做的。