2016-05-13 6 views
1

mit würde ich meine tkinter Anwendung wie die ausgewählten Elemente eines listbox von einem gerufenen Fenster (Klasse MyDialog) an das anrufende Fenster (Klasse zurückzukehren Beispiel). Wenn ich wait_window() nicht verwende, wird eine leere Liste zurückgegeben. Die Verwendung von wait_window() führt zu einer Fehlermeldung. Mir scheint, dass wait_window() die Methode curselection() blockiert. Was muss für eine ordnungsgemäße Rückkehr geändert werden? Das folgende Beispiel ist eine modifizierte Version von this answer.Wie die ausgewählten Elemente eines listbox zurückzukehren, wenn wait_window() in tkinter

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() 

Antwort

1

wait_window wartet, bis die Witwe zerstört ist. Und da es zerstört ist, können Sie keine Informationen aus dem Widget ziehen.

Sie müssen Bindungen einrichten, die die Daten in einer Variablen speichern, wenn sie sich ändert, sodass Sie sie abrufen können, nachdem das Widget zerstört wurde.

+0

Ich sehe, ich werde es versuchen. Aber warum funktioniert die Rückgabe mit einem Optionsmenü wie im Originalbeispiel? – AnBe

+0

@AnBe: weil das Optionsmenü den Wert in einer Variablen speichert, die _nicht_ zerstört wird, wenn das Widget zerstört wird. –

0

Bryan Oakleys Antwort führte mich zu der unten angegebenen Lösung. Vielen Dank!

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() 

     # add binding 
     self.listbox.bind('<<ListboxSelect>>', self.getSelection) 

    # function associated with binding 
    def getSelection(self, event): 
     widget = event.widget 
     selection=widget.curselection() 
     self.value = widget.get(selection[0]) 

    # separate function for wait_window and the return of the selection 
    def returnValue(self): 
     self.toplevel.wait_window() 
     return self.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).returnValue() 
     self.label.configure(text="your result: %s" % result) 

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