如何将事件传递给父窗口小部件

ste*_*fen 1 python tkinter

Tkinter是否可以将事件直接传递给父窗口小部件?

我有一块画布被其他画布的网格所覆盖(是复数吗?),我是用这种parent_canvas.create_window()方法添加的.我想要一些事件,例如鼠标释放事件,由父画布处理.

如果我只将事件绑定到父方法,则event.xevent.y坐标相对于捕获事件的子画布.

Bry*_*ley 5

Tkinter不会将事件传递给父窗口小部件.但是,您可以通过使用绑定标记(或"bindtags")来模拟效果.

我可以给出的最简单的解释是:当您向窗口小部件添加绑定时,您没有向窗口小部件添加绑定,而是绑定到"绑定标记".此标记与窗口小部件的名称相同,但实际上并不是窗口小部件.

窗口小部件有一个绑定标记列表,因此当窗口小部件上发生事件时,将按顺序处理每个标记的绑定.通常订单是:

  1. 实际小部件上的绑定
  2. widget类上的绑定
  3. 包含小部件的顶级窗口小部件上的绑定
  4. 绑定"所有"

请注意,该列表中的任何地方都不是"父窗口小部件上的绑定".

您可以将自己的bindtags插入该顺序.因此,例如,您可以将主画布添加到每个子画布的绑定标记中.当你绑定到任何一个时,函数将被调用.因此,似乎将事件传递给父级.

这是一些用python 2.7编写的代码示例.如果单击灰色方块,您将看到打印出的两个内容,显示子画布上的绑定和主画布上的绑定都会触发.如果单击粉红色正方形,您将看到子画布绑定触发,但它会阻止父绑定触发.

这样,所有按钮点击实际上都"传递"到父级.子画布可以控制父级是否应该处理事件,如果它想要"破坏"事件处理链,则返回"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()
Run Code Online (Sandbox Code Playgroud)