Python + Tkinter:“属性错误”

问题描述

我也没有太多的 Python 练习,并且在理解错误方面有一个基本问题:AttributeError: 'nonetype' object has no attribute '_root',它只在我定义 dec 变量时出现BEFORE 定义主窗口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()

为什么我必须首先定义窗口然后然后定义布尔变量?我从 Tkinter 中没有理解什么?

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

解决方法

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

StringVarIntVarDoubleVarBooleanVar 都继承自 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_default_root(如果你还没有创建一个 {{ 1}} 实例),这就是您收到 None 的原因。

但您可能会问,为什么同样的内容不适用于小部件?这是因为 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 的新实例作为 BaseWidget,而不是 tk。我的猜测是没有理由只为变量创建 _default_root 的实例,因为不需要在屏幕上呈现任何内容,但同样不能应用于小部件。

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

Tk