1

My understanding of tk.mainloop() was that it would run and handle the events of window related to the first created Tcl interpreter and <widget>.mainloop() would handle the events of the window related to the interpreter linked with the widget. Then I came across this code:

from tkinter import *

root1 = Tk()
root2 = Tk()

root1.mainloop() # Shouldn't this just handle the events of the first window

According to my understanding I thought this code was supposed to handle just the events related to root1, but root2 also comes up and it is responsive too(which means that its events are also being processed..?). Do correct me if my understanding of how mainloop() works is wrong.

Thanks :D

6
  • Basically you only need 1 .mainloop() in your code because it handles the events from all windows. Also look at the documentation, .mainloop() actually takes in 1 parameter, the number of Tk() windows left before the function returns. The default is 0. Commented Aug 15, 2021 at 14:43
  • @TheLizzard In that question the 2nd mainloop() is also called, but here it is not called. Commented Aug 15, 2021 at 14:47
  • Replacing .mainloop() with while True: root1.tk.dooneevent(_tkinter.DONT_WAIT), still has the same effect. Therefore, the question is actually about how tcl handles multiple tcl interpreters. Commented Aug 15, 2021 at 15:25
  • This says that you can have multiple tcl interpreters linked to 1 event queue. Commented Aug 15, 2021 at 15:36
  • 1
    I think the Notifier is just the event queue but it also handles after scripts. I might be misunderstanding that webpage. I think we should put the tcl tag. But I don't know much about this topic. Commented Aug 15, 2021 at 17:56

1 Answer 1

2

The mainloop() method runs the event processing loop on the current thread until all windows started in the thread have closed or the quit() method is called (which internally sets a flag that is checked by the core event loop runner). It blocks the thread, except that it does all the registered callbacks as necessary. The underlying machinery is not actually associated with any particular window, but rather with a thread. It's just that Tkinter prefers to not map things as free functions, despite that really being what they are.

You're pretty strongly recommended to not have the results of two calls to tkinter.Tk() active at once. It works, but the result can be quite confusing. It can get even more confusing if you do it from several threads at once (which is supposed to work — except on macOS for messy reasons — but the results tend to be mind-bending). (This does not apply to tkinter.Tcl(); that does work reasonably when done multiple times, and from multiple threads. The object it produces is thread-bound, but having many instances is sensible, and you can have those instances either in their own threads or together.)


What doing two calls to tkinter.Tk() like you've done does is create two separate underlying Tcl/Tk environments (the technical term is an “interpreter” even though that's got a bytecode compiler and so on) sharing a thread. This is sensible from a Tcl/Tk perspective due to the very different security model that Tcl uses, but it's almost total nonsense from the view of Python. The effects are describable small-scale operationally, but making broader sense of them is very difficult, and you're advised to not try.

Sign up to request clarification or add additional context in comments.

6 Comments

OH okay, so then what is the difference between tk.mainloop() and widget.mainloop()? They would behave the same way here
What makes me curious about your answer is that you can call the quit method on every window and the thread ends, at least it seems so and the windows are still responsible. So I think there needs to be difference between what runs in the IDE and in the OS shell.
There's no difference between them; widget.mainloop() is just an alias for tk.mainloop() and wouldn't have ever been made if I'd written Tkinter.
Bryan's a bit confused in that answer. The code doesn't use the first one, but rather uses the ones that the event handlers are registered to (this is a definitely known thing) and finds them on the current thread. If you've got Tkinter window stacks in several threads (not recommended!) then each of those threads needs its own main loop.
At the low level, each time you call tkinter.Tk() you get a new connection to the system event source (the X server, or the system message pump on Windows). That's then slotted into the per-thread notifier engine — a chunk of C code that knows how to wait for events efficiently — which powers the guts of mainloop(). There's a lot of other detail, but that's the heart of it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.