Tkinter - 了解如何切换帧

Posted

技术标签:

【中文标题】Tkinter - 了解如何切换帧【英文标题】:Tkinter - Understanding how to switch frames 【发布时间】:2016-03-21 22:57:18 【问题描述】:

我正在尝试自学如何使用 tkinter,但我通过 youtube 找到了一个我并不完全理解的有用代码。如果有人可以帮助我理解它,将不胜感激。用# ... **标记了我不明白的地方。

import tkinter as tk  # why not from tkinter import? **

class SampleApp(tk.Tk): # why tk.TK **

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

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others

        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.frames = 
        for F in (StartPage, PageOne, PageTwo):
            page_name = F.__name__
            frame = F(container, self) # **
            self.frames[page_name] = frame # **

            # put all of the pages in the same location;
            # the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise() # **


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent) # **
        self.controller = controller # **
        label = tk.Label(self, text="This is the start page",
                         font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)

        button1 = tk.Button(self, text="Go to Page One",
                            command=lambda: controller.show_frame("PageOne"))
        button2 = tk.Button(self, text="Go to Page Two",
                            command=lambda: controller.show_frame("PageTwo"))
        button1.pack()
        button2.pack()

【问题讨论】:

能否分享一下 youtube 链接? @BryanOakley 如果您还在寻找,我已经看到 this 教程使用来自 original question 的代码,尽管他确实说明了它的来源。还有this。 @double_j:是的,我很久以前就找到了,但是谢谢。我没有看到您提供的其他链接。我改进了原始答案,因此我可以知道谁开始使用我的代码以及谁开始使用该视频教程。该代码已经有了自己的生命,它出现在很多新手问题中。 【参考方案1】:
import tkinter as tk  # why not from tkinter import? **

为什么不from tkinter import *?因为那是错误的做法。 Global imports are bad。由于某些我不明白的原因,Tkinter 教程倾向于以错误的方式进行操作。

as tk 部分的原因是您可以使用tk.Frame 而不是tkinter.Frame,使代码更易于键入和阅读。这完全是可选的。


class SampleApp(tk.Tk): 

tk 是导入的 tkinter 模块的名称。 Tk 是该模块中代表根窗口的类的名称。每个 tkinter 应用程序都必须有一个根窗口。通过将其放置在SampleApp 中,这将创建此小部件的子类——具有附加功能的副本。

不必从tk.Tk 继承。您可以从tk.Frame、任何其他 tkinter 小部件甚至object 继承。这是个人喜好。选择让一些事情变得更容易,一些事情变得更难。


container = tk.Frame(self)

上面创建了一个Frame 小部件的实例,它将用作其他“页面”的容器。这些“页面”将在此容器中相互堆叠。


frame = F(container, self)

F 是循环变量。该循环正在遍历一个类列表,因此每次循环F 将代表一个类。 F(...) 创建类的一个实例。这些类(StartPagePageOnePageTwo)都需要两个参数:一个将成为此类父级的小部件,以及一个将作为 控制器 服务的对象(一个术语借鉴了 UI 模式model/view/controller)。

这行代码创建了该类的一个实例(它本身是Frame 小部件的子类),并将框架临时分配给局部变量frame

通过将self 作为第二个(“控制器”)参数传递,这些新类实例将能够调用SampleApp 类对象中的方法。

这会将对刚刚创建的框架的引用保存在字典中。字典的关键是页面名称(或更准确地说,是类的名称)。

这就是show_frame 方法如何仅根据类的名称来确定实际的页面小部件。

在循环中创建帧在功能上等同于以下内容:

f1 = StartPage(container, self)
f2 = PageOne(container, self)
f3 = PageTwo(container, self)

f1.grid(row=0, column=0, sticky="nsew")
f2.grid(row=0, column=0, sticky="nsew")
f3.grid(row=0, column=0, sticky="nsew")

self.frames = "StartPage": f1, "PageOne": f2, "PageTwo": f3

frame.tkraise() 

在几乎所有的 GUI 工具包中——包括 tkinter——都有“堆叠顺序”的概念:事物堆叠的顺序。一些工具包可能将此称为 z 顺序。如果两个或多个小部件相互堆叠(此代码通过将所有页面放在同一行和同一列中),则位于堆栈顶部的小部件通常是可见的。

tkraiseFrame 对象的一个​​方法,它将框架提升到堆叠顺序的顶部。在这行代码中,frame 指的是其中一个页面的一个特定实例。


tk.Frame.__init__(self, parent)

因为每个页面都是tk.Frame 类的子类,所以这会调用父类的构造函数。这是初始化构成实际框架小部件的所有内部结构所必需的。尽管Frame 可以采用许多选项,但此代码选择只发送一个——对另一个小部件的引用,该小部件将充当这个新小部件的父级。


self.controller = controller

上面的代码只是简单地“记住”了传入的controller 变量的值。在这种情况下,controller 是应用程序。通过保存它,这个类可以调用SampleApp 对象上的方法。


注意:问题中的代码来自从该答案复制代码的教程:https://***.com/a/7557028/7432。我是该原始代码的作者,但不是本教程的作者。该原始答案中包含与此代码相关的其他问题的链接。

【讨论】:

以上是关于Tkinter - 了解如何切换帧的主要内容,如果未能解决你的问题,请参考以下文章

tkinter - 使用按钮在帧之间来回切换

在 Tkinter 中切换帧时出错

使用 Tkinter 中的菜单栏在页面之间切换

python 3.x tkinter,将来自opencv cv2的帧集成到tkinter窗口中

我将如何制作一个每次在 tkinter 中显示帧时运行的方法

Python Tkinter:如何让画布每帧更新多边形坐标? [解决了]