Why are multiple instances of Tk discouraged?
The best reference I've found so far is the Application Windows section of the tkinterbook:
In the simple examples we’ve used this far, there’s only one window on the screen; the root window. This is automatically created when you call the Tk constructor
and
If you need to create additional windows, you can use the Toplevel widget. It simply creates a new window on the screen, a window that looks and behaves pretty much like the original root window
My take on it is that a Tk
instance creates a Toplevel
widget, plus things like the mainloop
, of which there should be only one.
I disagree with the tkinter
community discouraging the use of multiple tk.Tk
windows. You can have multiple tk.Tk
windows. Using multiple instances of tk.Tk
is the only way to create windows that are truly independent of each other. The only mistake most people make when creating multiple tk.Tk
windows is that they forget to pass in master=...
when creating PhotoImage
s/StringVar
s/IntVar
s/...
For example look at this code:
import tkinter as tk
root = tk.Tk()
root2 = tk.Tk()
variable = tk.StringVar() # Add `master=root2` to fix the problem
entry = tk.Entry(root2, textvariable=variable)
entry.bind("<Return>", lambda e: print(repr(variable.get())))
entry.pack()
root.mainloop()
The code above doesn't work. If you add master=root2
to the tk.StringVar()
, then it will work perfectly fine. This is because tkinter
stores the first instance of tk.Tk()
in tk._default_root
. Then if you don't pass in master=...
, it will assume that you wanted the window in tk._default_root
.
Another thing people get wrong is how many times should .mainloop()
be called. It handles events from all tk.Tk
windows that are alive so you only need one .mainloop()
.
For folks who disagree, I'd be interested in an example of where an actual problem is caused by the multiple tk.Tk
windows.
Why is it considered bad to have multiple instances of
Tk
?
Tkinter is just a python wrapper around an embedded Tcl interpreter that imports the Tk library. When you create a root window, you create an instance of a Tcl interpreter.
Each Tcl interpreter is an isolated sandbox. An object in one sandbox cannot interact with objects in another. The most common manifestation of that is that a StringVar
created in one interpreter is not visible in another. The same goes for widgets -- you can't create widgets in one interpreter that has as a parent widget in another interpreter. Images are a third case: images created in one cannot be used in another.
From a technical standpoint, there's no reason why you can't have two instances of Tk
at the same time. The recommendation against it is because there's rarely an actual need to have two or more distinct Tcl interpreters, and it causes problems that are hard for beginners to grasp.
Is the second snippet considered a bit better, or does it suffer from the same conditions the first code does?
It's impossible to say whether the second example in the question is better or not without knowing what you're trying to achieve. It probably is not any better since, again, there's rarely ever a time when you actually need two instances.
The best solution 99.9% of the time is to create exactly one instance of Tk
that you use for the life of your program. If you need a second or subsequent window, create instances of Toplevel
. Quite simply, that is how tkinter and the underlying Tcl/Tk interpreter was designed to be used.