Tkinter! Понимание того, как переключать кадры
Я пытаюсь научить себя, как использовать tkinter, и я нашел полезный код через Yo uTube, который я не совсем понимаю. Был бы признателен, если бы некоторые могли помочь мне понять это. Отмеченные вещи, которые я не понял с **
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()
1 ответ
import tkinter as tk # why not from tkinter import? **
Почему бы и нет from tkinter import *
? Потому что это неправильный способ сделать это. Мировой импорт - это плохо. Уроки 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
) все требуют два параметра: виджет, который будет родителем этого класса, и объект, который будет использоваться в качестве контроллера (термин, заимствованный из модели / представления / контроллера шаблона интерфейса пользователя).
Строка кода создает экземпляр класса (который сам является подклассом Frame
widget) и временно назначает кадр локальной переменной frame
,
Мимоходом self
как второй ("контроллер") параметр, эти новые экземпляры класса смогут вызывать методы в SampleApp
объект класса.
self.frames[page_name] = frame
Это сохраняет ссылку на только что созданный фрейм в словаре. Ключом к словарю является имя страницы (или, точнее, название класса).
Вот как show_frame
Метод может определить фактический виджет страницы только по названию класса.
frame.tkraise()
Почти во всех наборах инструментов с графическим интерфейсом, включая tkinter, существует понятие "порядок наложения": порядок, в котором вещи складываются. Некоторые наборы инструментов могут называть это z-порядком. Если два или более виджета накладываются друг на друга (что делает этот код, помещая все страницы в одну строку и столбец), виджет, который находится на вершине стека, является виджетом, который обычно будет виден.
tkraise
это метод Frame
объект, который поднимет рамку к вершине порядка наложения. В этой строке кода frame
относится к одному конкретному экземпляру одной из страниц.
tk.Frame.__init__(self, parent)
Потому что каждая страница является подклассом tk.Frame
класс, это вызывает конструктор родительского класса. Это необходимо для инициализации всех внутренних структур, которые составляют фактический виджет кадра. Хотя Frame
может принимать множество параметров, этот код выбирает отправку только одного - ссылки на другой виджет, который должен выступать в качестве родителя этого нового виджета.
self.controller = controller
Приведенный выше код просто "запоминает" значение controller
переменная, которая была передана. В этом случае controller
это приложение. Сохраняя его, этот класс может вызывать методы SampleApp
объект.
Примечание: код в вопросе взят из учебника, который скопировал код из этого ответа: /questions/37817041/pereklyuchenie-mezhdu-dvumya-kadrami-v-tkinter/37817042#37817042. Я являюсь автором этого оригинального кода, но не автором учебника. В этом оригинальном ответе есть ссылки на другие вопросы, связанные с этим кодом.