3

我也没有太多使用 Python 的实践,并且在理解错误时遇到了一个基本问题:AttributeError: 'NoneType' object has no attribute '_root',它只出现在我在定义主窗口win之前定义dec变量时:

import tkinter as tk
from tkinter import ttk
from tkinter import *

# This variable must be defined AFTER definition of the Tk() window!
dec = tk.BooleanVar()

# Main window
win = Tk()

# # This variable must be defined AFTER definition of the Tk() window!
# dec = tk.BooleanVar()


decreaseButton = Checkbutton(win, text = "Decrease (optional)", variable = dec)
decreaseButton.grid(row=1, column=1, sticky='W')


# Runs the event loop of Tkinter
win.mainloop()

为什么我必须先定义窗口然后再定义布尔变量?我对 Tkinter 有什么不明白的地方?

感谢大家的大力帮助和最良好的祝愿拉斯

4

1 回答 1

1

您实际上可以在 tkinter 的__init__.py.

StringVar, IntVar,DoubleVarBooleanVarall 继承自类Variable

class Variable:
    ...
    _default = ""
    _tk = None
    _tclCommands = None
    def __init__(self, master=None, value=None, name=None):
        ...
        if name is not None and not isinstance(name, str):
            raise TypeError("name must be a string")
        global _varnum
        if not master:
            master = _default_root
        self._root = master._root()
        self._tk = master.tk

    ...

因此,您会看到创建 tkinter 变量时,它会查找master存储为全局变量的 a _default_rootNone如果您尚未创建tk实例),这就是您收到AttributeError.

但你可能会问,为什么同样的方法不适用于小部件?这是因为Widgets继承自不同的基类,称为BaseWidgets

class BaseWidget(Misc):
    ...
    def _setup(self, master, cnf):
        ...
        if _support_default_root:
            global _default_root
            if not master:
                if not _default_root:
                    _default_root = Tk() <--- create a new instance of `Tk`
                master = _default_root

因此,您会看到,当您创建一个没有 master 的新小部件时,BaseWidget实际上会创建一个新实例,tk_default_root不是Variable. 我的猜测是没有理由Tk只为变量创建实例,因为不需要在屏幕上呈现任何内容,但同样不能应用于小部件。

因此,即使您自己没有创建Tk实例,以下内容也不会引发错误:

import tkinter as tk

a = tk.Button(text="ABC")

b = tk.BooleanVar()
于 2021-05-02T06:58:09.963 回答