AnBe AnBe - 6 months ago 30
Python Question

How to return the selected items of a listbox when using wait_window() in tkinter

I wish my tkinter application to return the selected items of a listbox from a called window (class MyDialog) to the calling window (class Example). If I would not use wait_window(), an empty list is returned. Using wait_window() results in an error message. It seems to me that wait_window() blocks the curselection() method. What needs to be changed for a proper return?

The example below is a modified version of this answer.

import tkinter as tk

class MyDialog(object):
def __init__(self, parent):
self.toplevel = tk.Toplevel(parent)

choices = ("one", "two","three")
names = tk.StringVar(value=choices)

label = tk.Label(self.toplevel, text="Pick something:")
self.listbox = tk.Listbox(self.toplevel, listvariable=names, height=3,
selectmode="single", exportselection=0)
button = tk.Button(self.toplevel, text="OK", command=self.toplevel.destroy)

label.pack(side="top", fill="x")
self.listbox.pack(side="top", fill="x")
button.pack()

def show(self):
self.toplevel.wait_window()

value = self.listbox.curselection()
return value

class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)

self.button = tk.Button(self, text="Click me!", command=self.on_click)
self.label = tk.Label(self, width=80)
self.label.pack(side="top", fill="x")
self.button.pack(pady=20)

def on_click(self):
result = MyDialog(self).show()
self.label.configure(text="your result: %s" % result)

if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()

Answer

wait_window waits until the widow is destroyed. And since it is destroyed, you can't pull any information out of the widget.

You must set up bindings that save the data to a variable when it changes, so that you can fetch it after the widget is destroyed.

Comments