Python + Tkinter:"AttributeError"

Python + Tkinter: "AttributeError"

我也没有太多使用 Python 的练习,并且有一个理解错误的基本问题:AttributeError: 'NoneType' object has no attribute '_root',只有在我定义 dec[ 时才会出现=25=] 变量 BEFORE 定义主要 window win:

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()

为什么我必须先定义 window 和 而不是 布尔变量?我从 Tkinter 中有什么不明白?

感谢大家的大力帮助和祝福 拉斯

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

StringVarIntVarDoubleVarBooleanVar 都继承自 class 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 变量时,它会查找一个存储为全局变量 _default_rootmaster(如果你还没有创建一个 None tk 实例),这就是为什么您会收到 AttributeError.

但是您可能会问,为什么这不适用于小部件?那是因为 Widgets 继承自一个名为 BaseWidgets:

的不同基 class
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

所以你看到当你创建一个没有母版的新小部件时,BaseWidget 实际上会创建一个 tk 的新实例作为 _default_root 而不是 Variable。我的猜测是没有理由只为变量创建 Tk 的实例,因为不需要在屏幕上呈现任何内容,但同样不能应用于小部件。

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

import tkinter as tk

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

b = tk.BooleanVar()