Python 3.x Tkinter-了解如何切换帧

Python 3.x Tkinter-了解如何切换帧,python-3.x,tkinter,Python 3.x,Tkinter,我试图教自己如何使用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

我试图教自己如何使用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()
为什么不从tkinter导入*
?因为那样做是错误的。Tkinter教程由于某些我不理解的原因,往往会以错误的方式进行

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


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

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


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


F
是循环变量。循环在类列表上迭代,因此每次通过循环
F
时都将表示一个类
F(…)
创建类的实例。这些类(
StartPage
PageOne
PageTwo
)都需要两个参数:作为此类父级的小部件,以及作为控制器服务的对象(从UI模式模型/视图/控制器借用的术语)

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

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

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

这就是
show\u 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}

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

tkraise
是将帧提升到堆叠顺序顶部的
Frame
对象的一种方法。在这行代码中,
frame
指的是其中一个页面的一个特定实例


因为每个页面都是
tk.Frame
类的子类,所以调用父类的构造函数。这是初始化组成实际框架小部件的所有内部结构所必需的。虽然一个
框架可以有很多选项,但是这个代码选择只发送一个——对另一个小部件的引用,它将作为这个新小部件的父部件


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



注意:问题中的代码来自从以下答案复制代码的教程:。我是原始代码的作者,但不是教程的作者。原始答案中包含与此代码相关的其他问题的链接。

您可以分享youtube链接吗?@BryanOakley如果您还在看,我已经看过使用您的代码的教程,尽管他确实说了代码的来源。还有。@double_j:是的,我刚才找到了,但是谢谢。我没有看到你提供的其他链接。我改进了原来的答案,这样我就可以知道谁是从我的代码开始的,谁是从那个视频教程开始的。这段代码已经有了自己的生命,它出现在很多新手的问题中。
class SampleApp(tk.Tk): 
container = tk.Frame(self)
frame = F(container, self)
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() 
tk.Frame.__init__(self, parent)
self.controller = controller