Skip to content Skip to sidebar Skip to footer

How To Wait For Result From Tkinter Toplevel Window Before Continuing?

After a user clicks on a button, I want to create a new TopLevel window with suggestions and when user selects his/her suggestion on the toplevel window and clicks the button 'Done

Solution 1:

The tkinter method wait_window does exactly what you want, though you could also use wait_visibility or even wait_variable. You claim wait_window is unreliable but that method has been a part of tk for decades and I've personally never seen it misbehave.

I recommend implementing this with two pieces of code: a class that implements the window itself, and a function which uses the class to display the window and return the selected item.

The following gives an example. Notice that the value self.selection is initialized to None, and then set to a value when the user clicks the "Confirm Selection" button. Also notice that the show method will get this value before destroying the widget so that it can be retrieved even after the widget has been destroyed.

classSuggestionPopup(tk.Toplevel):
    def__init__(self, parent, suggestions):
        super().__init__(parent)

        self.title("Select suggestion")

        self.listbox = tk.Listbox(self, height=10, width=20)
        self.listbox.pack(pady=15)

        self.btn = tk.Button(self, text="Confirm selection", command=self.select)
        self.btn.pack(pady=10)

        for (idd, info) in suggestions :
            self.listbox.insert(tk.END, info)

        self.selection = Nonedefselect(self):
        selection = self.listbox.curselection()
        if selection:
            self.selection = self.listbox.get(selection[0])
        self.destroy()

    defshow(self):
        self.deiconify()
        self.wm_protocol("WM_DELETE_WINDOW", self.destroy)
        self.wait_window(self)
        return self.selection

The function to display it might look something like this:

def get_suggestion():
    suggestions = ((0, "Item 0"), (1, "Item 1"), (2, "Item 2"))
    popup = SuggestionPopup(root, suggestions)
    result = popup.show()
    return result

Solution 2:

Alright I solved it by first checking whether something is selected and then destroy the toplevel window afterwards by having global reference to toplevel window. I also used wait_window to wait for the selection as @Bryan Oakley confirmed.

Final working code:

import tkinter as tk

root = None
BTN = None
listbox = None
selected = None
toplvlwin = None
SUGGESTIONS = [(0, "level 1"), (11, "level 2"), (23, "level 3")]

defselect():
    global listbox, SUGGESTIONS, selected, toplvlwin

    selection = listbox.get(tk.ANCHOR)
    for (idd, info) in SUGGESTIONS:
        if selection == f_info:
                selected = idd
                toplvlwin.destroy()

defshow_suggestions():
    global SUGGESTIONS, listbox, selected, toplvlwin 

    toplvlwin = tk.TopLevel()
    toplvlwin.title("Select suggestion")
    toplvlwin.geometry("400x400")
    
    listbox = tk.Listbox(win, height=20, width=40)
    listbox.pack(pady=15)

    self.btn = tk.Button(win, text="Confirm selection", command=select)
    self.btn.pack(pady=10)

    for (idd, info) in SUGGESTIONS :
        self.listbox.insert(tk.END, f_info) 
    
    toplvlwin.wait_window()

    print(selected) # confirm correct tuple id is returneddefmain():
    global root, BTN
    root = tk.Tk()
    root.title("Youtube to MP3")
    root.geometry("575x475")

    BTN = tk.Button(
        master=root,
        text="List suggestions",
        width=25,
        height=5,
        command=show_suggestions
    )
    BTN.pack(pady=15)
    
    root.mainloop()

Post a Comment for "How To Wait For Result From Tkinter Toplevel Window Before Continuing?"