How to register events on tkinter child widgets?

In the next block, clicking on a_framestarts an event handler on_frame_click, but clicking on a_label, which is a child a_frame, does not work. Is there a way to force a_framechildren to catch and process events that occurred on it (preferably without the need to add handlers to children directly)? I am using 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()
+5
source share
3 answers

Yes, you can do what you want, but it takes a little work. It’s not that it is not supported, it’s just that in fact it’s quite rare to need something like this so that it is not by default.

TL DR - tkinter binding tag research

Tkinter " ". , . , . , . , . "break", .

, , , , , , "". , , .

? , , . , ( , - ):

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()

bindtags Tkinter , ?. , , , .

+13

( ), - .

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)

, a_frame a_frame <Button>, a_frame e.widget.master , , . , , , .

+4

According to what he says in the Binding Levels section of this Tkinter online link , it looks like this is possible because you can bind a handler to three different levels.
Summarizing:

  • Instance Level: Binding an event to a specific widget.
  • Class Level: Bind an event to all widgets of a specific class.
  • Application level: independent widget - certain events always invoke a specific handler.

See the first link for details.

Hope this helps.

0
source

All Articles