How To Wait For Result From Tkinter Toplevel Window Before Continuing?
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?"