I recently started to use tkwait casually and noticed that some functionality only works under special conditions. For example:
import tkinter as tk
def w(seconds):
dummy = tk.Toplevel(root)
dummy.title(seconds)
dummy.after(seconds*1000, lambda x=dummy: x.destroy())
dummy.wait_window(dummy)
print(seconds)
root = tk.Tk()
for i in [5,2,10]:
w(i)
root.mainloop()
The code above works just fine and as expected:
- The for loop calls the function
- The function runs and blocks the code for x seconds
- The window gets destroyed and the for loop continues
But in a more event driven environment these tkwait
calls gets tricky. The documentation states quote:
If an event handler invokes tkwait again, the nested call to tkwait must complete before the outer call can complete.
Instead of an output of >>5
>>2
>>10
you will get >>10
>>2
>>5
because the nested call blocks the inner and the outer will block the inner. I suspect a nested event loop or an equivalent of the mainloop processes events in the normal fashion while waiting.
Am I doing something wrong by using this feature? Because if you think about it, nearly all tkinter dialog windows are using this feature and I've never read about this behavior before.
An event driven example might be:
import tkinter as tk
def w(seconds):
dummy = tk.Toplevel(root)
dummy.title(seconds)
dummy.after(seconds*1000, lambda x=dummy: x.destroy())
dummy.wait_window(dummy)
print(seconds)
root = tk.Tk()
btn1 = tk.Button(
root, command=lambda : w(5), text = '5 seconds')
btn2 = tk.Button(
root, command=lambda : w(2), text = '2 seconds')
btn3 = tk.Button(
root, command=lambda : w(10), text = '10 seconds')
btn1.pack()
btn2.pack()
btn3.pack()
root.mainloop()
As an additional problem that raises with wait_something
is that it will prevent your process to finish if the wait_something
never was released.