Tkinter:window 在 GUI 中导航

Tkinter: window navigation inside a GUI

几天前我发布了一个关于这个主题的问题,但由于我在那个问题中的示例代码是错误的,所以我删除了那个主题以提供更清晰的示例代码。 在 Tkinter 构建的 GUI 中浏览不同 pages/windows 的最佳做法是什么?简单地说,我希望能够通过菜单栏中的命令浏览应用程序中的不同页面。我想避免将页面堆叠在一起,我更喜欢使用 grid_remove()pack_forget() 的方法。 我在这里找到的唯一其他教程使用堆叠方法和 lift()。还有其他更好的方法吗?

import tkinter as tk
from tkinter import *


class MainWin(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.page_1 = Page1(self.parent)
        self.page_2 = Page2(self.parent)

        self.init_UI()

    def init_UI(self):
        menubar = Menu(self.parent)
        self.parent.config(menu=menubar)
        self.parent.title('Frame Switching test app')
        file_menu = Menu(menubar)
        pages_menu = Menu(menubar)
        menubar.add_cascade(label='File', menu=file_menu)
        file_menu.add_command(label='Exit', command=self.on_exit)
        menubar.add_cascade(label='Pages', menu=pages_menu)
        pages_menu.add_command(label='Pages 1', command=self.page_1.show)
        pages_menu.add_command(label='Page 2', command=self.page_2.show)

    def on_exit(self):
        self.quit()


class Page1(LabelFrame):
    def __init__(self, parent):
        LabelFrame.__init__(self, parent)
        self.parent = parent
        self.config(text='This is page 1 label Frame')
        self.sample_text = Label(self, text='You are viewing Page 1')

    def show(self):
        self.pack(fill=BOTH, expand=1)
        self.sample_text.grid(in_=self)
        self.lift()

    def close(self):
        self.pack_forget()


class Page2(LabelFrame):
    def __init__(self, parent):
        LabelFrame.__init__(self, parent)
        self.parent = parent
        self.config(text='This is page 2 label Frame')
        self.sample_text = Label(self, text='You are viewing Page 2')

    def show(self):
        self.pack(fill=BOTH, expand=1)
        self.sample_text.grid(in_=self)
        self.lift()

    def close(self):
        self.pack_forget()


def main():
    root = tk.Tk()
    app = MainWin(root)
    root.mainloop()


if __name__ == '__main__':
    main()

已经有一个 question and answer 展示了如何堆叠帧。要切换到使用 grid_forgetpack_forget 的模式,您只需更改调用 lift 的代码,改为在当前页面上调用适当的 "forget" 方法(你需要跟踪),然后添加新的 window.

如果您想按需创建页面,并在不使用时销毁它们,那也很容易。唯一真正的区别是您在请求之前不创建页面,并在完成后将其删除。否则实现是相同的。

以下是按需创建页面的示例。从 this answer 中的代码开始,将 SampleApp class 修改为如下所示:

class SampleApp(tk.Tk):

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

        # the container is where we'll pack the current page
        self.container = tk.Frame(self)
        self.container.pack(side="top", fill="both", expand=True)
        self.current_frame = None

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''

        # destroy the old page, if there is one
        if self.current_frame is not None:
            self.current_frame.destroy()

        # create the new page and pack it in the container
        cls = globals()[page_name]
        self.current_frame = cls(self.container, self)
        self.current_frame.pack(fill="both", expand=True)