Return Daten von einem zu schließenden Fenster

Fragen zu Tkinter.
Antworten
LT67
User
Beiträge: 6
Registriert: Sonntag 4. Oktober 2015, 10:19

Hallo,
ich arbeite erst seit ca. zwei Monaten mit Python und bin neu in diesem Forum. Ich stehe vor folgendem Problem (oder vielleicht stehe ich auf dem Schlauch). Ich möchte, dass, wenn in einem Fenster der "OK" Button gedrückt wird, das Fenster geschlossen wird und verschiedene Werte zurückgibt.
Für den Datentyp "Liste" bekomme ich es hin, für "Integer" und "Boolean" jedoch nicht. Insgesamt habe ich den Eindruck, dass es nicht "sauber" programmiert ist. Ist das überhaupt der richtige Ansatz (ich möchte ungern mit "global" arbeiten)? Kann mir jemand weiterhelfen?

Vielen Dank

Henning

Code: Alles auswählen

import tkinter

def showWindow():
    liste = []
    zahl = 0
    erfolg = False
    

    class myWindow(tkinter.Frame):
     
        def __init__(self, root: tkinter.Tk):
            # init Window via super
            super().__init__(root)
            self.pack()
            self.createForm ()

            
        def createForm(self):
            self.txtInput = tkinter.Entry(self)
            self.txtInput.pack()

            btnOk = tkinter.Button(self, text = "OK", command=self.cmdOk)
            btnOk.pack()

        def cmdOk(self):
            liste.append(self.txtInput.get())
            zahl = 5
            erfolg = True
            root.destroy()

    root = tkinter.Tk()
    mw = myWindow(root)
    root.mainloop()

    return (liste, zahl, erfolg)
            
print (showWindow())
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@LT67: Deine Frage ist schwierig zu beantworten, da GUI-Programme nicht so linear ablaufen, wie Du Dein Programm strukturiert hast. Bei Tk gibt es ein Hauptfenster, und dass etwas wesentliches nach dem Schließen des Hauptfensters passiert ist ungewöhlich.

Neben global gibt es auch nocht nicht-lokal. In der Methode cmdOk sind liste und root nicht-lokal, zahl und erfolg sind lokal. Statt nicht-lokaler Variablen würde man aber besser Attribute nehmen.

Code: Alles auswählen

import tkinter

class SomeFrame(tkinter.Frame):
    def __init__(self, root):
        super().__init__(root)
        self.root = root
        self.text = ''
        self.zahl = 0
        self.erfolg = False
        self.txtInput = tkinter.Entry(self)
        self.txtInput.pack()
        btnOk = tkinter.Button(self, text = "OK", command=self.cmdOk)
        btnOk.pack()

    def cmdOk(self):
        self.text= self.txtInput.get()
        self.zahl = 5
        self.erfolg = True
        self.root.destroy()

def main():
    root = tkinter.Tk()
    mw = SomeFrame(root)
    mw.pack()
    root.mainloop()
    print(mw.text, mw.zahl, mw.erfolg)

if __name__ == '__main__':
    main()
BlackJack

Eventuell würde es sich auch lohnen von der Dialog-Klasse aus der Standardbibliothek zu erben. Für Einzelwerte gibt's sogar schon Funktionen wie `askstring()` oder `askinteger()`.
LT67
User
Beiträge: 6
Registriert: Sonntag 4. Oktober 2015, 10:19

Hallo Sirius, hallo BlackJack,

vielen Dank für die schnelle Antwort. Der Programmcode funktioniert.

Ich habe noch zwei Verständnisfragen:

Mit mainloop() übergebe ich die Kontrolle für den weiteren Ablauf an das Fenster "root". In Zeile 19 zerstöre ich "root" kann aber in Zeile 26 auf "SomeFrame", was doch ein Kind von "root" ist, zugreifen? Und Zeile 26 ist m.E. zeitlich Zeile 19 nachgelagert. Ich würde erwarten, dass auch "SomeFrame" mit "root" zerstört wurde. Wo mache ich den Denkfehler?

Wenn dieses Fenster eigentlich von einem Hauptfenster aufgerufen wird, um Daten vom User für zu erfragen (bspw. Einstellungen mit denen eine Funktion später aus dem Hauptmenü ausgeführt werden soll (z.B. der Code für die Verschlüsselung eines beliebigen Textes)), ändert sich dann am Problem mit der Übergabe der Variablen etwas? Auch weiterhin möchte ich nach dem Drücken von "OK" Daten übergeben und das Fenster zerstören. Oder würde man da einen anderen Ansatz wählen?

Vielen Dank für Eure Hilfe

Henning
BlackJack

@LT67: Die `destroy()`-Methode zerstört das angezeigte Widget, aber nicht die Python-Objekte.

Wenn das Fenster von einem Hauptfenster aus aufgerufen wird muss sich auf jeden Fall der Typ ändern, denn das `Tk`-Exemplar ist *das* Hauptfenster. Wenn es davon schon eines gibt, darf man kein weiteres erstellen, sonst passieren komische Sachen. Für weitere Fenster gibt es `Toplevel`. Für solche Dialoge würde ich dann aber tatsächlich die angebotene Dialog-Klasse(n) als Basis nehmen. In Python 2.x heisst das Modul `tkSimpleDialog` — in Python 3.x ist das wohl umbenannt worden.
LT67
User
Beiträge: 6
Registriert: Sonntag 4. Oktober 2015, 10:19

Hallo BlackJack,

das das Python-Objekt weiter existiert, habe ich bisher nicht gewusst. Vielen Dank für den Hinweis.

Henning
Antworten