Что на самом деле делает вызов Tk ()?

я чистил на Tkinter, когда я посмотрел на минимальный пример из NMT Tkinter 8.5 ссылка.

#!/usr/bin/env python
import tkinter as tk

class Application(tk.Frame):    
    def __init__(self, master=None):    
        tk.Frame.__init__(self, master)
        self.grid()
        self.createWidgets()

    def createWidgets(self):    
        self.quitButton = tk.Button(self, text='Quit',command=self.quit)
        self.quitButton.grid()

app = Application()
app.master.title('Sample application')
app.mainloop()

все хорошо и хорошо, пока я не замечу, что Tk класс не инициализируется. В других онлайн-справочных материалах я мог найти (ссылка на библиотеку Python, effbot.org, TkDocs), обычно есть вызов root = tk.Tk(), из которого построены остальные примеры. Я тоже не видел никакой ссылки на Tk инициализация класса в любом месте ссылки NMT.

информация, которую я мог бы получить относительно Tk класс также расплывчат, а ссылка Python только перечисляет его как " виджет верхнего уровня ... который обычно является главным окном приложения". Наконец, если я заменю последние строки в фрагменте, который я представил ранее:

root = tk.Tk()
app = Application(root)

программа будет работать так же, как и раньше. Помня обо всем этом, я ... интересно знать это:

  • что вызов root = tk.Tk() на самом деле (как в, что инициализируется) и почему предыдущий фрагмент может работать без него?
  • столкнусь ли я с какими-либо ловушками или ограничениями, если я не позвоню Tk() и просто построил мое приложение вокруг Frame класса?

3 ответов


Tkinter работает, запустив интерпретатор tcl/tk под обложками, а затем переведя команды tkinter в команды tcl/tk. Главное окно и этот интерпретатор внутренне связаны, и оба необходимы для работы приложения tkinter.

создание экземпляра Tk инициализирует этот интерпретатор и создает корневое окно. Если вы явно не инициализируете его, он будет неявно создан при создании первого виджета.

Я не подумайте, что есть какие-то подводные камни, не инициализируя его самостоятельно, но, как утверждает Дзен python, "явное лучше, чем неявное". Ваш код будет немного легче понять, если вы явно создадите экземпляр Tk. Это, например, помешает другим людям задавать тот же вопрос о вашем коде, который вы только что задали об этом другом коде.


Брайан Окли ответ на месте. Создание виджета будет имплицитно создайте экземпляр интерпретатора tcl/tk. Однако я хотел бы добавить некоторые фрагменты кода, чтобы лучше понять, как ТК создается неявно.

всякий раз, когда создается объект виджета (будь то кадр или кнопка или даже виджет на основе ttk),BaseWidget класса __init__ вызывается метод, который, в свою очередь, называет _setup метод. Вот фрагмент соответствующая часть:

def _setup(self, master, cnf):
    """Internal function. Sets up information about children."""
    if _support_default_root:
        global _default_root
        if not master:
            if not _default_root:
                _default_root = Tk()
            master = _default_root
    self.master = master
    self.tk = master.tk

и _support_default_root и _default_root являются глобальными переменными, объявленными в строках 132-133 на tkinter пакета. Они инициализируются следующими значениями:

_support_default_root = 1
_default_root = None

это означает, что если master не предоставляется, и если интерпретатор еще не был создан, экземпляр Tk создается и назначается в качестве корня по умолчанию для всех будущих виджеты.

там тоже что-то интересное при создании пример Tk класса. Следующий фрагмент происходит из Tk._loadtk способ:

if _support_default_root and not _default_root:
    _default_root = self

это означает, что независимо от того, как Tk класс инициализируется, он всегда настраивается как корень по умолчанию.


иногда некоторые виджеты работать Tk() по собственному желанию. Но я не знаю, какие виджеты и почему.

иногда она работает даже если вы не используете mainloop() - в основном на Windows.

Tkinter странная обертка на Tcl /Tk:)

но я предпочитаю использовать root = Tk() и root.mainloop() всегда.