Skip to main content
 首页 » 编程设计

python之如何将事件传递给父 tkinter 小部件

2025年05月04日31webabcd

在 Tkinter 中是否可以将事件直接传递给父部件?

我有一个 Canvas ,上面覆盖着其他 Canvas 的网格(这是复数形式吗?),我使用 parent_canvas.create_window() 方法添加了它。我希望某些事件(例如鼠标释放事件)由父 Canvas 处理。

如果我只将事件绑定(bind)到父方法,则 event.x 和 event.y 坐标会相对于捕获事件的子 Canvas 出现。

请您参考如下方法:

Tkinter 不会将事件传递给父部件。但是,您可以通过使用绑定(bind)标签(或“bindtags”)来模拟效果。

我能给出的最简短的解释是:当您将绑定(bind)添加到小部件时,您并不是在向小部件添加绑定(bind),而是绑定(bind)到“绑定(bind)标签”。此标记与小部件同名,但实际上并不是小部件。

小部件有一个绑定(bind)标签列表,所以当一个事件发生在一个小部件上时,每个标签的绑定(bind)都会按顺序处理。通常顺序是:

  1. 在实际小部件上的绑定(bind)
  2. 小部件类的绑定(bind)
  3. 在包含小部件的顶层小部件上的绑定(bind)
  4. 绑定(bind)“所有”

请注意,该列表中的任何地方都没有“父小部件上的绑定(bind)”。

您可以在该订单中插入您自己的绑定(bind)标签。因此,例如,您可以将主 Canvas 添加到每个子 Canvas 的绑定(bind)标签中。当您绑定(bind)到其中任何一个时,该函数将被调用。因此,看起来事件已传递给父级。

这是一些用 python 2.7 编写的示例代码。如果你点击一个灰色的方 block ,你会看到两件事被打印出来,表明子 Canvas 上的绑定(bind)和主 Canvas 上的绑定(bind)都被触发了。如果单击粉红色方 block ,您会看到子 Canvas 绑定(bind)已触发,但它会阻止父绑定(bind)触发。

这样一来,所有按钮的点击实际上都“传递”给了父级。子 Canvas 可以控制父 Canvas 是否应该处理事件,如果它想“打断”事件处理的链条,则返回“break”。

import Tkinter as tk 
 
class Example(tk.Frame): 
    def __init__(self, parent): 
        tk.Frame.__init__(self, parent) 
 
        self.main = tk.Canvas(self, width=400, height=400,  
                              borderwidth=0, highlightthickness=0, 
                              background="bisque") 
        self.main.pack(side="top", fill="both", expand=True) 
 
        # add a callback for button events on the main canvas 
        self.main.bind("<1>", self.on_main_click) 
 
        for x in range(10): 
            for y in range(10): 
                canvas = tk.Canvas(self.main, width=48, height=48,  
                                   borderwidth=1, highlightthickness=0, 
                                   relief="raised") 
                if ((x+y)%2 == 0): 
                    canvas.configure(bg="pink") 
 
                self.main.create_window(x*50, y*50, anchor="nw", window=canvas) 
 
                # adjust the bindtags of the sub-canvas to include 
                # the parent canvas 
                bindtags = list(canvas.bindtags()) 
                bindtags.insert(1, self.main) 
                canvas.bindtags(tuple(bindtags)) 
 
                # add a callback for button events on the inner canvas 
                canvas.bind("<1>", self.on_sub_click) 
 
 
    def on_sub_click(self, event): 
        print "sub-canvas binding" 
        if event.widget.cget("background") == "pink": 
            return "break" 
 
    def on_main_click(self, event): 
        print "main widget binding" 
 
if __name__ == "__main__": 
    root = tk.Tk() 
    Example(root).pack (fill="both", expand=True) 
    root.mainloop()