英文:
Doing something when a tkinter frame is shown
问题
我正在尝试编写一个应用程序,每当显示特定的帧时,都需要执行一些逻辑。从这些问题的建议中here,here 和 here,我编写了以下结构化的代码:
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) -> None:
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) -> None:
'''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()
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) -> None:
'''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.wait_visibility()
frame.event_generate("<<ShowFrame>>")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论