当 tkinter 框架显示时执行某操作。

huangapple go评论52阅读模式
英文:

Doing something when a tkinter frame is shown

问题

我正在尝试编写一个应用程序,每当显示特定的帧时,都需要执行一些逻辑。从这些问题的建议中hereherehere,我编写了以下结构化的代码:

import tkinter as tk
from tkinter import ttk

class MainApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.madlibs_source = ""

        self.frames = {
            "PageOne":  PageOne(
                parent=container,
                controller=self,
                ),
            "PageTwo": PageTwo(
                parent=container,
                controller=self,
                ),
            "PageThree": PageThree(
                parent=container,
                controller=self,
                ),
            }

        self.frames["PageOne"].grid()

    def show_frame(self, page_name: str):
        '''Show a frame for the given page name'''
        for frame in self.frames.values():
            frame.grid_remove()
        frame = self.frames[page_name]
        frame.grid()
        frame.event_generate("<<ShowFrame>>")

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        page_two_button = ttk.Button(
            self,
            text="Page 2",
            command=lambda: self.controller.show_frame("PageTwo"),
            )
        page_two_button.pack(padx="10", pady="10")

        page_three_button = ttk.Button(
            self,
            text="Page 3",
            command=lambda: self.controller.show_frame("PageThree"),
            )
        page_three_button.pack(padx="10", pady="10")

class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        page_three_button = ttk.Button(
            self,
            text="Page 3",
            command=lambda: self.controller.show_frame("PageThree"),
            )
        page_three_button.pack(padx="10", pady="10")

class PageThree(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        some_label = tk.Label(self, text="This is page three")
        some_label.pack()
        self.bind("<<ShowFrame>>", self.frame_shown)

    def frame_shown(self, event):
        print("Doing something")

if __name__ == "__main__":
    root = MainApp()
    root.mainloop()

从这个代码中,我期望每当显示第三页时,将运行frame_shown方法,并且"Doing Something"将被输出到控制台,但似乎并不是这样。有谁能指出我哪里出错了?

英文:

I am trying to write an application which requires some logic to be performed every time a particular frame is shown. Taking advice from the questions here, here and here, I have come up with some code structured like this:

import tkinter as tk
from tkinter import ttk


class MainApp(tk.Tk):
    def __init__(self, *args, **kwargs) -&gt; None:
        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side=&quot;top&quot;, fill=&quot;both&quot;, expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.madlibs_source = &quot;&quot;

        self.frames = {
            &quot;PageOne&quot;:  PageOne(
                parent=container,
                controller=self,
                ),
            &quot;PageTwo&quot;: PageTwo(
                parent=container,
                controller=self,
                ),
            &quot;PageThree&quot;: PageThree(
                parent=container,
                controller=self,
                ),
            }

        self.frames[&quot;PageOne&quot;].grid()

    def show_frame(self, page_name: str) -&gt; None:
        &#39;&#39;&#39;Show a frame for the given page name&#39;&#39;&#39;
        for frame in self.frames.values():
            frame.grid_remove()
        frame = self.frames[page_name]
        frame.grid()
        frame.event_generate(&quot;&lt;&lt;ShowFrame&gt;&gt;&quot;)


class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        page_two_button = ttk.Button(
            self,
            text=&quot;Page 2&quot;,
            command=lambda: self.controller.show_frame(&quot;PageTwo&quot;),
            )
        page_two_button.pack(padx=&quot;10&quot;, pady=&quot;10&quot;)

        page_three_button = ttk.Button(
            self,
            text=&quot;Page 3&quot;,
            command=lambda: self.controller.show_frame(&quot;PageThree&quot;),
            )
        page_three_button.pack(padx=&quot;10&quot;, pady=&quot;10&quot;)


class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        page_three_button = ttk.Button(
            self,
            text=&quot;Page 3&quot;,
            command=lambda: self.controller.show_frame(&quot;PageThree&quot;),
            )
        page_three_button.pack(padx=&quot;10&quot;, pady=&quot;10&quot;)


class PageThree(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        some_label = tk.Label(self, text=&quot;This is page three&quot;)
        some_label.pack()
        self.bind(&quot;&lt;&lt;ShowFrame&gt;&gt;&quot;, self.frame_shown)

    def frame_shown(self, event):
        print(&quot;Doing something&quot;)


if __name__ == &quot;__main__&quot;:
    root = MainApp()
    root.mainloop()

I would expect from this that whenever page three is shown, the frame_shown method would be run and "Doing Something" would be output to the console, but this doesn't seem to to be the case. Can anybody point out where I'm going wrong?

答案1

得分: 0

我的猜测是事件没有被处理,因为在生成事件时,帧不可见。我在文档中没有看到关于这一点的说明,但这是我唯一能想到的解释。

如果在生成事件之前等待窗口可见,事件将按预期处理。您可以通过在生成事件之前调用frame.wait_visibility()来实现这一点。

英文:

My guess is that the event isn't being processed since the frame isn't visible at the time that you generate the event. I didn't see anything in the documentation about this, but that's the only explanation I can think of.

If you wait for the window to be visible before generating the event, the event will be processed as expected. You can do that by calling frame.wait_visibility() before generating the event.

    def show_frame(self, page_name: str) -&gt; None:
&#39;&#39;&#39;Show a frame for the given page name&#39;&#39;&#39;
for frame in self.frames.values():
frame.grid_remove()
frame = self.frames[page_name]
frame.grid()
frame.wait_visibility()
frame.event_generate(&quot;&lt;&lt;ShowFrame&gt;&gt;&quot;)

huangapple
  • 本文由 发表于 2023年7月14日 04:12:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76682939.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定