I also have not a lot of practice with Python and have a fundamental problem of understanding the error: AttributeError: 'NoneType' object has no attribute '_root', which only appears, when I define the dec variable BEFORE defining the main 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()
Why do I have to define first the window and than the Boolean variable? What did I not understand from Tkinter?
Thank you everybody for your great help and with best wishes Lars
You can actually look this up at tkinter's __init__.py.
StringVar, IntVar, DoubleVar and BooleanVar all inherits from the 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
...
So you see when a tkinter variable is created, it will lookup for a master stored as a global variable _default_root (which is None if you have yet to create a tk instance), which is why you receive a AttributeError.
But you might ask, why the same does not apply to widgets? That is because Widgets inherits from a different base class called 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
So you see when you create a new widget without a master, BaseWidget will actually create a new instance of tk as _default_root as opposed to Variable. My guess is that there is no reason to create an instance of Tk just for a variable since nothing needs to be rendered on screen, but the same cannot be applied for a widget.
As such, the below doesn't throw an error even you did not create a Tk instance yourself:
import tkinter as tk
a = tk.Button(text="ABC")
b = tk.BooleanVar()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With