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. Я являюсь автором этого оригинального кода, но не автором учебника. В этом оригинальном ответе есть ссылки на другие вопросы, связанные с этим кодом.

Другие вопросы по тегам