Reputation: 31
Why doesn't clicking on a child element propagate to the parent?
from tkinter import *
root = Tk()
def handler(event):
print('clicked at', event.x, event.y)
frame = Frame(root, width=100, height=100)
label = Label(frame, text="Label")
frame.bind('<Button-1>', handler)
frame.pack()
label.pack(side=TOP)
root.mainloop()
When I run that, clicking on the label doesn't fire the handler. I've understood that events propagate to parents by default and if you didn't want that, you'd have to return "break"
Upvotes: 3
Views: 2256
Reputation: 386342
You are incorrect in your original understanding that events propagate to their parent. They do not.
Admittedly, there's an edge case for widgets which are a direct descendant of a toplevel or root window. Even there, it's not that they are propagating to their parent, but rather they are being handled by other bindings as defined by the bind tags, and by default every widget has it's toplevel window as one of it's bind tags.
If you want to set a binding to work everywhere you can use the bind_all
method, since each widget has an "all" bindtag by default. Another option is to give several widgets the same bindtag (using the bindtags
method), then bind to that bindtag with bind_class
. Which choice you make depends on what you are trying to accomplish.
bindtags are extremely powerful -- arguably more powerful than any binding mechanisms from any other toolkit. For example, if you need to have events propagate you can do that by adjusting the bindtags of every widget to include all of its ancestors. In my experience, however, such shenanigans is rarely ever needed.
Upvotes: 5
Reputation: 310167
You're mistaken. "break"
causes that event to not propagate to other handlers for the widget that was clicked on.
In other words, if you bound your action to label
and then you bound another action to the first button onto label
, both callbacks will be called (unless you return "break"
from the first one to be called.)
I'm not sure of a workaround though ... (We might need to wait for BryanOakley to show up ;)
Upvotes: 0