17

It seems that the object that calls this method waits for the window passed as parameter to be destroyed before continue with its own loop...

From the doc strings of the Misc class, we can observe:

def wait_window(self, window=None):
    """Wait until a WIDGET is destroyed.
    If no parameter is given self is used."""

At first glance, it seems like this method can make a Toplevel modal, but this is not true. To make a Toplevel modal, we have to use the grab_set() method.

I have see around other explanations:

wait_window seems to not return until the given widget passed as parameter is not destroyed.

From another place:

wait_window(widget) - Creates a local event that waits for the given widget to be destroyed. This loop doesn't affect the application's mainloop.

From the effbot documentation, we have:

The wait_window enters a local event loop, and doesn’t return until the given window is destroyed (either via the destroy method, or explicitly via the window manager):

widget.wait_window(window)

What exactly means for a window to wait for window (itself)?

It seems that the code that comes after the call to wait_window is not executed until the window passed to the same method is not destroyed. In the following working example, we can see a proof on what just said:

from tkinter import *

def on_win_request(parent):
    dialog = Toplevel()
    parent.wait_window(dialog)
    # executed only when "dialog" is destroyed
    print("Mini-event loop finished!")

r = Tk()
b = Button(r, text='New Window', command=lambda: on_win_request(r))
b.pack()
b2 = Button(r, text='Hello!', command=lambda: print("hello"))
b2.pack()
r.mainloop()

"Mini-event loop finished!" will be printed only when the local Toplevel widget called dialog is destroyed.

So, in exactly what real circumstances should I use this method?

nbro
  • 15,395
  • 32
  • 113
  • 196
  • I seems to block the application in the constructor until the dialogue window is destroyed. You wouldn't want to wait on the parent, as you only want to block until the user interacts with the dialogue. I haven't given a proper answer as I'm have not done GUI programming in ages and am not sure how the main thread deals with GUI events. – Jmac Feb 08 '15 at 01:14
  • @Jmac Why would I not want to wait on the parent? The parent waits for the dialog, as far as I have understood. Basically what would happen is that the window for which parent waits, enters in its own local loop. – nbro Feb 08 '15 at 01:50
  • @Jmac As far as it's stated on `effbot`, `wait_window` enters a local event loop, and does not return until the given window as parameter is destroyed. So, in the case we call `wait_window` on the parent, we would enter on a local loop (I suppose on the dialog, or maybe not?) and we would not return the control to the parent until the dialog is destroyed... – nbro Feb 08 '15 at 01:53
  • @Jmac Maybe it does not make any difference to call the `wait_window` on self or on the parent, from this statement in the `effbot` documentation: `Note that the method waits until the window given as an argument is destroyed. The only reason this is a method is to avoid namespace pollution.` – nbro Feb 08 '15 at 01:59
  • @Jmac Then there's another example, where is the `root` waiting for the `Toplevel`: `root.wait_window(d.top)`, that's why maybe it's basically the parent that let's the child to run on a local loop, which does not stop until the child is destroyed. – nbro Feb 08 '15 at 02:02
  • My previous comment was a little misinformed: ignore it. After rereading, wait_window seems to block until an event occurs in the window given and will return when the destroy window event occurs in the window given. In that case, calling the child's wait_window is exactly the same as calling the parent's. – Jmac Feb 08 '15 at 02:49
  • It seems cleaner to me to have self.wait_window rather than self.parent.wait_window. It is the _child's_ init method waiting for events to occur in the child, rather than the parent waiting for events. If you create the parent class, may be able to have to parent window call its wait_window method on the child. In this simple example though, the parent is the root, so calling wait_window from the child makes the most sense – Jmac Feb 08 '15 at 02:51

1 Answers1

22

Like the documentation states, it waits until the given window is destroyed. It is mostly used for modal popups, though it doesn't itself make a window modal. The call to the function simply doesn't return until the target window is destroyed To make a modal window you have to do a grab as well.

The most common use is to create an instance of Toplevel, populate that window with widgets, then wait for the window to be dismissed before doing some other action. While it is waiting, tkinter is able to continue to process events as normal.

For instance, you can disable (or defer creation of) the main GUI, pop up a "terms of service" notice, and wait for the user to acknowledge the terms of service, copyright, license, etc. Once the window is destroyed you can then finish initialization, or enable some widgets, etc.

The standard file dialog is a perfect example: you pop up the dialog, then your code waits for the user to pick a file, then it uses the filename that was returned. Internally, the implementation of the dialog uses wait_window so that it doesn't return until the dialog is dismissed.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • 1
    I understood that, but in what real circumstances should it be useful? Could you please show me some examples? – nbro Mar 18 '15 at 12:56
  • @rinzler: the file dialog is an example: ask the user to pick a file, then load the file. Alert windows are another example. On platforms that lack native dialogs, the dialogs are implemented as toplevel windows and use `wait_window` to wait for the user to click a button, select a file, pick a font, etc. – Bryan Oakley Mar 18 '15 at 12:59
  • 1
    But in some examples, we have `window.wait_window(window)`, what exactly does this mean to a window wait for itself? What's the difference respect to `root.wait_window(window)`? – nbro Mar 18 '15 at 13:04
  • I have read somewhere that the only reason that `wait_window` is a method and not a global function is to reduce namespace pollution, so I suppose there's no difference... – nbro Mar 18 '15 at 13:11
  • 1
    @Rinzler: think of the inner workings of the file dialog: it waits for itself. You don't have to add code in your app to wait for the dialog to be destroyed, because the dialog does that for you. – Bryan Oakley Mar 18 '15 at 13:15