0

I have searched stackoverflow and found various answers, but can't figure out the why. Hoping someone can help or simply point me to somewhere that I could read about the following tkinter issue (self taught, trying to learn tkinter).

I try to follow the approach set forth in "A Simple Hello World Program" at https://docs.python.org/3/library/tkinter.html. And it works and all is good. But I'm experimenting to get to a bare minimum to understand things better and have what I believe to be a chicken and egg conundrum.

This code works just fine to give me a window:

import tkinter as tk
root = tk.Tk()
root.mainloop()

Code noted below works if I put the code above "root =" and does not if below "root =".

var = StringVar()
label = tk.Label(root, textvariable=var, relief=RAISED)
var.set("Hey!? How are you doing?")
label.pack()

I get an error stating "'NoneType' object has no attribute '_root'". I understand it is because root has yet to be defined.

I think Brian Oakley superbly answered my question at AttributeError: 'NoneType' object has no attribute '_root' He wrote: "You cannot create an instance of StringVar until after the root window has been created."

What I'm wondering is why is that the case? I want to understand why as I think it will make me a better programmer. And I've looked and can't put my finger on the why.

wiseass
  • 543
  • 2
  • 5
  • 11
  • "Code noted below works if I put the code above "root =" and does not if below "root ="." Is that supposed to be the other way around? `tk` implementation details aside, `tk.Label(root, ...)` raises a `NameError` if you haven't actually defined the variable `root` yet. – chepner Jun 03 '20 at 22:53

1 Answers1

1

why does tkinter root in Python need to be created first?

Tkinter is a wrapper around an embedded tcl/tk interpreter. Every tkinter object represents an object in this embedded interpreter. The interpreter isn't initialized until you create the root window. It is impossible to create a tkinter object which exists in this interpreter until the interpreter exists, so you must create the root window before creating any tkinter objects.

Also, widgets exist in a tree like hierarchy. By definition a tree requires a root. It is literally impossible to create any widget (except the root window itself) without an existing root window. If you create a widget without creating a root window, one will be created for you. That does not happen, however, when you create one of the special Tkinter variables (StringVar, etc).

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I know you advocate an OOP and have indicated you preferred approach https://stackoverflow.com/questions/17466561/best-way-to-structure-a-tkinter-application – wiseass Dec 11 '20 at 13:45
  • I know you advocate an OOP and have indicated you preferred approach https://stackoverflow.com/questions/17466561/best-way-to-structure-a-tkinter-application. And in that post your highest level class was tk.Frame. But why not have the first class be the root window and have everything inherit from that top level class? – wiseass Dec 11 '20 at 13:55
  • @wiseass: inheritance isn't for sharing data. There should never be more than one root window, so inheriting from such a class wouldn't make any sense. I don't see what that has to do with this answer, though. – Bryan Oakley Dec 11 '20 at 14:08