调用Tk()实际上做了什么?

Dok*_*ard 10 python tk-toolkit tkinter

当我看到NMT Tkinter 8.5参考文献中的一个最小例子时,我正在刷Tkinter.

#!/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()
Run Code Online (Sandbox Code Playgroud)

这一切都很好,直到我注意到Tk该类没有被初始化.在我可以找到的其他在线参考资料(Python的库参考,effbot.org,TkDocs)中,通常会调用root = tk.Tk()其他示例构建的参考资料.我也没有Tk在NMT的引用上看到任何类型的初始化类引用.

我可以得到的有关Tk该类的信息也很模糊,Python Reference仅将其列为"顶级窗口小部件......通常是应用程序的主窗口".最后,如果我替换前面提到的代码段中的最后几行:

root = tk.Tk()
app = Application(root)
Run Code Online (Sandbox Code Playgroud)

该程序将像以前一样运行.考虑到这一切,我有兴趣知道的是:

  • 调用root = tk.Tk()实际上是做什么的(例如,什么被初始化)以及为什么前一个片段在没有它的情况下工作?
  • 如果我不打电话Tk()并在Frame课堂上构建我的应用程序,我会遇到任何陷阱或限制吗?

Bry*_*ley 14

Tkinter通过在封面下启动tcl/tk解释器,然后将tkinter命令转换为tcl/tk命令来工作.主窗口和此解释器是内在链接的,两者都是tkinter应用程序工作所必需的.

创建Tk初始化此解释器的实例并创建根窗口.如果您没有显式初始化它,则在创建第一个窗口小部件时将隐式创建一个.

我不认为自己没有初始化会有任何陷阱,但正如蟒蛇国家的禅宗,"显性比隐性更好".如果您明确创建实例,您的代码将更容易理解Tk.例如,它会阻止其他人询问您刚才询问有关此其他代码的代码的相同问题.


Dok*_*ard 7

布莱恩奥克利的答案是正确的。创建小部件将隐式创建 tcl/tk 解释器的实例。然而,我想添加一些代码,以更好地理解 Tk 是如何隐式创建的。

每当创建 Widget 对象时(无论是 Frame 还是 Button 甚至是基于 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
Run Code Online (Sandbox Code Playgroud)

这两个_support_default_root_default_root是全局变量,在线条的132-133宣布__init__.py在文件tkinter包。它们被初始化为以下值:

_support_default_root = 1
_default_root = None
Run Code Online (Sandbox Code Playgroud)

这意味着,如果master未提供,并且尚未创建解释器,则会创建一个实例Tk并将其分配为所有未来小部件的默认根。

创建Tk类的实例时还有一些有趣的事情。以下代码段来自该Tk._loadtk方法:

if _support_default_root and not _default_root:
    _default_root = self
Run Code Online (Sandbox Code Playgroud)

这意味着,无论Tk类如何初始化,它始终设置为默认根。