How to capture events on tkinter child widgets?

后端 未结 4 1816
谎友^
谎友^ 2021-02-15 13:51

In the following block, clicking on a_frame triggers the event handler on_frame_click, but clicking on a_label which is a child of a

4条回答
  •  悲&欢浪女
    2021-02-15 14:16

    Yes, you can do what you want, but it requires a bit of work. It's not that it's not supported, it's just that it's actually quite rare to need something like this so it's not the default behavior.

    TL;DR - research "tkinter bind tags"

    The Tkinter event model includes the notion of "bind tags". This is a list of tags associated with each widget. When an event is received on a widget, each bind tag is checked to see if it has a binding for the event. If so, the handler is called. If not, it continues on. If a handler returns "break", the chain is broken and no more tags are considered.

    By default, the bind tags for a widget are the widget itself, the widget class, the tag for the toplevel window the widget is in, and finally the special tag "all". However, you can put any tags you want in there, and you can change the order.

    The practical upshot of all this? You can add your own unique tag to every widget, then add a single binding to that tag that will be processed by all widgets. Here's an example, using your code as a starting point (I added a button widget, to show this isn't something special just for frames and labels):

    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", "

    For more on bindtags, you might be interested in my answer to the question How to bind self events in Tkinter Text widget after it will binded by Text widget?. The answer addresses a different question than the one here, but it shows another example of using bind tags to solve real world problems.

提交回复
热议问题