The normal way within tkinter
is to run all windows within one "mainloop". You can also run a mainloop in a separate process, and each process can run a mainloop independently.
The other answer now has an example of the "within one mainloop" way - maybe later I'll edit in my own example here.
Here's a minimal example of how run "mainloop" in separate processes:
import multiprocessing
import tkinter
# Note, due to a quirk of multprocessing and pickle,
# you can't just copy-paste this in the interactive
# Python REPL, it has to go in a file.
def ui():
tkinter.Tk().mainloop()
if __name__ == '__main__':
multiprocessing.Process(target=ui).start()
# The above line did not block, because mainloop
# ran in another process. So now we can run more
# mainloops in parallel if we want:
multiprocessing.Process(target=ui).start()
I wouldn't do this unless each window is its own independent app that just happens to be launched from one parent process for some reason, or you have some other really good reason to isolate it.
As for why it doesn't work:
window.mainloop
is a blocking/ongoing operation - it kinda hints at this by having "loop" in the name - inside that function is what's called an "event loop", and the code just sits in that loop waiting for and handling window events until the window is closed.
You can think of it almost like this:
def mainloop():
while window_exists:
...
# this is why it doesn't work
# it loops forever in here
for i in range(n):
mainloop()
For more detail, you can dive into the tkinter
documentation where you'll find similar explanations:
Tcl/Tk applications are normally event-driven, meaning that after initialization, the interpreter runs an event loop [...] This is different from many GUI toolkits where the GUI runs in a completely separate thread from all application code including event handlers.
In principle, multiple threads or processes could run one event loop each, but in this case, tkinter
assumes that Tcl (and thus Tk) was not compiled with thread-safety (ruling out threads).