Rückgabewert aus einem Child Fenster übernehmen

Fragen zu Tkinter.
Antworten
mkoathome
User
Beiträge: 2
Registriert: Mittwoch 26. Juni 2019, 10:23

Ich möchte ein Modul schreiben das aus mehren Eingabefeldern per Doppelklick aufgerufen werden kann und dessen Rückgabewert nach Schließen des fensters in das entsprechende Parent Eingabefld übernommen wir. Hier mein bisheriges Codefragment

Code: Alles auswählen

''' Diese Module öffent ein Child Fenster und erwartet eine Eingabe
    Der eingegebene Wert soll in das aufrufende Feld aus dem Parent
    Fenster übernommen werden

'''

import tkinter as tk

__version__ = '0.1'

class ChildWindow(object):

    returnval = None
    
    def __init__(self, parent, values):
        self.root = tk.Toplevel(parent)
        self.values = values
        self.setup('dummy')
         
    def setup(self, text):
        self.text = text
        self.labl = tk.Label(self.root, height=2, text=self.values)
        self.entry = tk.Entry(self.root, justify='center')
        self.entry.insert(tk.END, self.text)
        self.ok = tk.Button(self.root, width=5, text='OK',
                            command=self.kill_and_save)
        self.labl.grid()
        self.entry.grid()
        self.ok.grid()
        ChildWindow.returnval = self.text
         
    def kill_and_save(self):
        ChildWindow.returnval = self.entry.get()
        self.root.destroy()
 
if __name__ == '__main__':
 
    class ParentWindow:
        def __init__(self, parent):
            self.parent = parent
            self.data1 = 'test1'
            self.data2 = 'test2'
            self.entry1 = tk.Entry(self.parent, justify='center')
            self.entry2 = tk.Entry(self.parent, justify='center')
            self.show_btn = tk.Button(self.parent, text='Show value',
                                      command=self.print_value)
            self.entry1.insert(tk.END, self.data1)
            self.entry2.insert(tk.END, self.data2)
            self.entry1.bind("<Double-Button-1>",
                             lambda
                             p1=self.parent, p2=self.data1:self.popup(p1, p2))
            self.entry2.bind("<Double-Button-1>",
                             lambda
                             p1=self.parent, p2=self.data2:self.popup(p1, p2))
            self.entry1.grid()
            self.entry2.grid()
            self.show_btn.grid()
             
        def popup(self, evt, data):
            ret = ChildWindow(self.parent, data)
             
        def print_value(self):
            # for debug only
            print(ChildWindow.returnval)
            print(self.data1, self.data2)            
 
    root = tk.Tk()
    app = ParentWindow(root)
    root.mainloop()
Bin für jeden Hinweis dankbar.
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Warum definierst du ParentWindow innerhalb des __main__-Guard? Das ist ungewoehnlich und unnoetig. Was dafuer fehlt ist eine echte main-Funktion, die du aus dem __main__-Guard aufrufst, und in der die letzten drei Zeilen deines Codes stehen.

Childwindow.returnval ist effektiv eine globale Variable, und damit schon ein Fuss in der Programmierhoelle.

Was dein eigentliches Problem angeht: so geht GUI-Programmierung nicht. Ereignisse haben per Definition keine Rueckgabewerte, und dementsprechend koennen sie auch kein return sinnvoll nutzen. Die Loesung liegt ueblicherweise in callbacks.

Code: Alles auswählen

''' Diese Module öffent ein Child Fenster und erwartet eine Eingabe
    Der eingegebene Wert soll in das aufrufende Feld aus dem Parent
    Fenster übernommen werden

'''

import tkinter as tk

__version__ = '0.1'

class ChildWindow(object):

    def __init__(self, parent, values, value_callback=lambda value: None):
        self.root = tk.Toplevel(parent)
        self.values = values
        self.setup('dummy')
        self._value_callback = value_callback

    def setup(self, text):
        self.text = text
        self.labl = tk.Label(self.root, height=2, text=self.values)
        self.entry = tk.Entry(self.root, justify='center')
        self.entry.insert(tk.END, self.text)
        self.ok = tk.Button(self.root, width=5, text='OK',
                            command=self.kill_and_save)
        self.labl.grid()
        self.entry.grid()
        self.ok.grid()

    def kill_and_save(self):
        self._value_callback(self.entry.get())
        self.root.destroy()


class ParentWindow:
    def __init__(self, parent):
        self.parent = parent
        self.data1 = 'test1'
        self.data2 = 'test2'
        self.entry1 = tk.Entry(self.parent, justify='center')
        self.entry2 = tk.Entry(self.parent, justify='center')
        self.show_btn = tk.Button(self.parent, text='Show value',
                                  command=self.print_value)
        self.entry1.insert(tk.END, self.data1)
        self.entry2.insert(tk.END, self.data2)
        self.entry1.bind("<Double-Button-1>",
                         lambda
                         p1=self.parent, p2=self.data1:self.popup(p1, p2))
        self.entry2.bind("<Double-Button-1>",
                         lambda
                         p1=self.parent, p2=self.data2:self.popup(p1, p2))
        self.entry1.grid()
        self.entry2.grid()
        self.show_btn.grid()

    def popup(self, evt, data):
        def store_value(value):
            self._value = value

        ChildWindow(self.parent, data, store_value)

    def print_value(self):
        print(self._value)


def main():
    root = tk.Tk()
    app = ParentWindow(root)
    root.mainloop()


if __name__ == '__main__':
    main()
mkoathome
User
Beiträge: 2
Registriert: Mittwoch 26. Juni 2019, 10:23

@__deets__:
Warum definierst du ParentWindow innerhalb des __main__-Guard?
Ich wollte eigentlich ein Modul schreiben das ich in verschiedenen anderen Modulen mit jeweils unterschiedlichen Parent Windows importieren kann um den Code effizient nutzen zu können. Daher war hier das Parent Window im __main__-Guard für Testzwecke definiert.

Childwindow.returnval ist effektiv eine globale Variable
Das war mein workaround um überhaupt irgendwas zurück zu bekommen. Bin froh dass ich noch nicht vollkommen gebraten bin :)

Die Loesung liegt ueblicherweise in callbacks.
Danke, das war wohl was mir fehlte. Muss ich mich jetzt erstmal intensiv mit beschäftigen.
Antworten