我试图教我自己如何使用tkinter,我通过youtube找到了一个有用的代码,我并不完全理解。如果有人能帮助我理解它,我将不胜感激。用**
标记我不理解的东西import tkinter as tk # why not from tkinter import? **
class SampleApp(tk.Tk): 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()
答案 0 :(得分:17)
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(...)
创建该类的实例。这些类(StartPage
,PageOne
,PageTwo
)都需要两个参数:一个将成为此类父级的小部件,以及一个将作为控制器服务器的对象< / em>(从UI模式借用的术语模型/视图/控制器)。
代码行创建了一个类的实例(它本身是Frame
小部件的子类),并暂时将该框架分配给局部变量frame
。
通过传递self
作为第二个(“controller”)参数,这些新的类实例将能够调用SampleApp
类对象中的方法。
self.frames[page_name] = frame
这将保存对字典中刚刚创建的帧的引用。字典的关键是页面名称(或更准确地说,是类的名称)。
这就是show_frame
方法只能从类的名称确定实际页面窗口小部件的方式。
frame.tkraise()
在几乎所有的GUI工具包中 - 包括tkinter - 都有“堆叠顺序”的概念:事物堆叠的顺序。有些工具包可能称之为z顺序。如果两个或多个窗口小部件堆叠在一起(这个代码通过将所有页面放在同一行和列中来完成),则堆栈顶部的窗口小部件通常是可见的窗口小部件。
tkraise
是Frame
对象的一种方法,它会将帧提升到堆叠顺序的顶部。在这行代码中,frame
引用其中一个页面的一个特定实例。
tk.Frame.__init__(self, parent)
因为每个页面都是tk.Frame
类的子类,所以这会调用父类的构造函数。这是初始化构成实际框架窗口小部件的所有内部结构所必需的。虽然Frame
可以有很多选项,但是这段代码只选择发送一个 - 对另一个小部件的引用,该小部件将充当这个新小部件的父级。
self.controller = controller
上面的代码只是“记住”传入的controller
变量的值。在这种情况下,controller
是应用程序。通过保存它,该类可以调用SampleApp
对象上的方法。
注意:问题中的代码来自一个复制此答案代码的教程:https://stackoverflow.com/a/7557028/7432。我是原始代码的作者,但不是本教程的作者。原始答案是指向与此代码相关的其他问题的链接。