You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Tkinter中实现嵌套类间的事件通信?

Tkinter自定义事件跨类触发问题解决

问题原因

你当前的代码里,Nested类调用self.event_generate("<<MyEvent>>")时,只会在Nested这个Frame实例上生成事件,但Main类是在自己的实例上绑定的<<MyEvent>>。Tkinter的自定义虚拟事件默认不会向上传播,所以Main的绑定无法捕获到Nested实例上生成的事件。

解决方案

方案1:直接在目标组件上生成事件

既然Main类是事件的绑定者,就让NestedMain的实例上生成事件。修改Nested__init__方法,把self.event_generate换成针对父组件(即Main实例)的调用:

import tkinter as tk

root = tk.Tk()

class Main(tk.Frame):
    class Nested(tk.Frame):
        def __init__(self, parent) -> None:
            tk.Frame.__init__(self, parent)
            # 改为在父组件(Main实例)上生成事件
            parent.event_generate("<<MyEvent>>", when="tail")

    def __init__(self, parent) -> None:
        tk.Frame.__init__(self, parent)
        self.event_add("<<MyEvent>>", "<Button-1>")
        self.bind("<<MyEvent>>", self.foo)
        self.nested = self.Nested(self)
        self.nested.grid(column=0, row=0)

    def foo(self, event):
        print("event occured")

main = Main(root)
main.grid(column=0, row=0)
root.mainloop()

方案2:全局触发(顶层窗口级别)

如果需要让事件在整个应用内全局生效,可以把事件绑定到顶层窗口(root),然后在Nested里向顶层窗口生成事件:

import tkinter as tk

root = tk.Tk()

class Main(tk.Frame):
    class Nested(tk.Frame):
        def __init__(self, parent) -> None:
            tk.Frame.__init__(self, parent)
            # 向顶层窗口生成事件
            self.winfo_toplevel().event_generate("<<MyEvent>>", when="tail")

    def __init__(self, parent) -> None:
        tk.Frame.__init__(self, parent)
        self.event_add("<<MyEvent>>", "<Button-1>")
        # 把绑定移到顶层窗口
        parent.bind("<<MyEvent>>", self.foo)
        self.nested = self.Nested(self)
        self.nested.grid(column=0, row=0)

    def foo(self, event):
        print("event occured")

main = Main(root)
main.grid(column=0, row=0)
root.mainloop()

额外说明

你之前尝试用winfo_toplevel()没效果,是因为事件绑定在Main实例上,而不是顶层窗口。只要把绑定目标和事件生成目标对应起来,就能解决问题,不需要调整整体GUI结构。

内容的提问来源于stack exchange,提问作者domino280d

火山引擎 最新活动