Seite 1 von 1
Tkinter Popup Fenster richtig schliessen?
Verfasst: Dienstag 23. April 2019, 10:10
von PythonMan2019
Hallo
habe da ein relativ triviales Problem:
Ein Popup Fenster soll aufgehen und Werte in die entsprechenden Felder eingegeben werden.
Danach kann man das Fenster wieder mit OK schliessen.
Nach dem Mainloop() habe ich die Funktion aufgerufen.
Aber es taucht eine Fehlermeldung auf.....
Der Code:
Code: Alles auswählen
from Tkinter import *
_A_P_=""
_List = []
def RFD_ChoicePopup():
_A_P_ = _A_P.get()
_List=[_A_P_]
master.quit()
try:
master.destroy()
except:
pass
return _List
master = Tk()
Label(master, text="Checkpoints / Variant:\n ",font = ("arial", 11, "bold")).grid (row=0, column=0, columnspan=2, sticky=W)
Label(master, text="ACP \n").grid (row=1, column=0, sticky=E)
_A_P = Entry(master)
_A_P.insert(10,"Miller")
_A_P.grid(row=1, column=1)
Button(master,text='OK',command=RFD_ChoicePopup).grid(row=10,column=0,sticky=W,pady=5)
master.geometry("300x330+750+350")
mainloop()
print RFD_ChoicePopup()
Fehlermeldung:
Traceback (most recent call last):
File "C:\Program Files (x86)\Common Files..\Pythonwin\pywin\framework\scriptutils.py", line 307, in RunScript
debugger.run(codeObject, __main__.__dict__, start_stepping=0)
File "C:\Program Files (x86)\Common Files\..s\Pythonwin\pywin\debugger\__init__.py", line 60, in run
_GetCurrentDebugger().run(cmd, globals,locals, start_stepping)
File "C:\Program Files (x86)\Common Files\...\Pythonwin\pywin\debugger\debugger.py", line 631, in run
exec cmd in globals, locals
File "C:\Users\...\Script1.py", line 42, in <module>
print RFD_ChoicePopup()
File "C:\Users\a...\Script1.py", line 9, in RFD_ChoicePopup
_A_P_ = _A_P.get()
File "C:\Program Files (x86)\Common Files\....\Python25\Lib\lib-tk\Tkinter.py", line 2371, in get
return self.tk.call(self._w, 'get')
TclError: invalid command name ".48604384"
>>>
Kann mir einer sagen, warum ich die Funktion nach dem mainloop nicht ausführen kann?
Grüße
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Dienstag 23. April 2019, 10:44
von Sirius3
@PythonMan2019: Python2 ist veraltet und Python2.5 erst recht. Warum verwendest Du so eine alte Version?
Sternchenimporte vermeiden. Sinnvolle Namen vergeben. _A_P-irgendwas hat mich fünfmal lesen gekostet, bis ich verstanden habe, was Du da eigentlich machst. Alles was mit einem _ anfängt, bedeutet, dass die Variable nicht verwendet wird. Das erste _A_P wird aber auch gar nicht verwendet.
Das globale _List ist auch nicht aussagekräftiger, wird aber auch gar nicht verwendet.
Bei Dir ist das Gegenteil der Fall. Variablennamen und Funktionsnamen schreibt man klein_mit_unterstrich.
Keine nackten Excepts und keine globalen Variablen benutzen. _A_P und master tauchen auf magische Weise in RFD_ChoicePopup auf, was sie nicht sollten.
Rückgabewerte bei Ereignisbearbeitung sind unsinnig, weil sie nicht weiter verwendet werden. Eine Liste mit nur einem Element ist auch irgendwie unsinnig.
Du rufst get auf einem TK-Widget auf, nachdem Du den master per destroy zerstört hast. Das geht nicht.
Hast Du Dir soetwas vorgestellt?
Code: Alles auswählen
import Tkinter as tk
def popup():
master = tk.Tk()
master.geometry("300x330+750+350")
tk.Label(master, text="Checkpoints / Variant:", font=("arial", 11, "bold")).grid(row=0, column=0, columnspan=2, sticky=tk.W)
tk.Label(master, text="ACP").grid(row=1, column=0, sticky=tk.E)
name = tk.Entry(master)
name.insert(10, "Miller")
name.grid(row=1, column=1)
tk.Button(master, text='OK', command=master.quit).grid(row=10, column=0, sticky=tk.W, pady=5)
master.mainloop()
result = name.get()
master.destroy()
return result
def main():
print popup()
if __name__ == '__main__':
main()
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Dienstag 23. April 2019, 10:50
von __blackjack__
@PythonMan2019: Nach der Hauptschleife ist das Programm zuende und alle GUI-Elemente sind zerstört. Es macht auch gar keinen Sinn die Funktion an der Stelle aufzurufen, denn ohne das die Hauptschleife läuft, funktioniert diese Funktion nicht. Auch ein Rückgabewert macht bei dieser Funktion keinen Sinn, denn der wird an die Hauptschleife zurückgegeben und die erwartet keine Rückgabewerte von Funktionen die als Rückruffunktion für `command` aufgerufen werden. Du hast eine falsche Vorstellung wie GUI-Programme funktionieren. Nicht mehr Du hast den Programmfluss direkt unter Kontrolle, sondern Du kannst nur auf Ereignisse reagieren. Das führt unweigerlich dazu das man für jedes nicht-triviale GUI-Programm objektorientierte Programmierung braucht, weil man sich über Rückrufe hinweg Daten und Zustand merken muss.
Sonstiges: Es macht keinen Sinn heute noch ein neues Programm mit Python 2 anzufangen:
https://pythonclock.org/
Sternchen-Importe sind Böse™. Bei `Tkinter` holt man sich so fast 190 Namen in das Modul von denen nur ein ganz kleiner Bruchteil tatsächlich verwendet wird. Es wird schwerer nachzuvollziehen wo Namen her kommen und es besteht die Gefahr von Namenskollisionen.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Alles was eine Funktion oder Methode ausser Konstanten benötigt sollte als Argument(e) übergeben werden, also *keine* globalen Variablen.
Einen Namen der später an ein `Entry` gebunden wird, sollte vorher nicht an eine leere Zeichenkette gebunden werden. Manchmal *braucht* man das, dass man einen Namen definieren möchte, aber das endgültige Objekt erst später erzeugt – dann kann man `None` als ”Platzhalter” verwenden. Aber in diesem Fall gibt es absolut keinen Grund dafür. Es schaut eher so aus als wenn der Programmablauf nicht verstanden wurde. Das gleiche gilt für `_List` auf Modulebene: Das wird nirgends verwendet, kann also weg. Sollte da sowieso nicht stehen, genau wie das `Entry`, weil auf Modulebene keine Variablen gehören.
Die Namen sind fast alle überarbeitungswürdig. Namen schreibt man in Python klein_mit_unterstrichen. Ausnahmen: Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Und man verwendet keine kryptischen Abkürzungen. Zudem haben Grunddatentypen wie `list` nichts im Namen verloren. Man ändert während der Programmentwicklung öfter mal den Datentyp und dann hat man entweder falsche, irreführende Namen im Programm, oder muss alle betroffenen Namen anpassen. Das ist fehleranfällig und macht nur unnötig Arbeit.
Keine nackten ``except``\s verwenden ohne die konkrete(n) Ausnahme(n) die man da erwartet und behandeln will. Und *jede* Ausnahme einfach komplett zu *ignorieren* ist eigentlich *nie* eine sinnvolle Behandlung.
Warum fügst Du etwas am Index 10 in ein garantiert leeres Eingabefeld ein?
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Dienstag 23. April 2019, 10:58
von PythonMan2019
Hallo
danke für die hilfreichen Informationen. Werde diese beherzigen!!!
Ja, ihr habt recht. Ich bin gerade noch dabei die ganzen Funktionen von Tkinter zu lernen.
Ich gehe alles nochmal step-by-step durchs Tutorial.
Habt ihr denn ein geeignetes Tutorial?
Grüße
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Donnerstag 25. April 2019, 07:36
von PythonMan2019
Hallo
das Popup Fenster habe ich soweit angepasst und es funktioniert gut.
Einziges Problem ist, wenn ich auf das Kreuz oben rechts im Fenster drücke um das Fenster abzubrechen, taucht folgende Fehlermeldung:
Traceback (most recent call last):
File "C:\Users\User\Documents\...\Pythonwin\pywin\framework\scriptutils.py", line 311, in RunScript
debugger.run(codeObject, __main__.__dict__, start_stepping=0)
File "C:\Users\User\Documents\...\Pythonwin\pywin\debugger\__init__.py", line 60, in run
_GetCurrentDebugger().run(cmd, globals,locals, start_stepping)
File "C:\Users\User\...\Pythonwin\pywin\debugger\debugger.py", line 631, in run
exec cmd in globals, locals
File "C:\Users\User\..\Script1.py", line 21, in <module>
main()
File "C:\Users\User\..\Script1.py", line 18, in main
print popup()
File "C:\Users\User\..\Script1.py", line 13, in popup
result = name.get()
File "C:\Users\User\..\Lib\lib-tk\Tkinter.py", line 2371, in get
return self.tk.call(self._w, 'get')
TclError: invalid command name ".117426256"
Wie kriege ich es hin, dass ich das Fenster schliessen kann, ohne dass irgendetwas übernommen wird und er einfach abbricht?
Gruss
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Donnerstag 25. April 2019, 07:47
von Sirius3
Es ist doch schonmal gut, dass eine Exception geworfen wird, wenn das Fenster einfach so geschlossen wird. So kannst Du gültige Eingaben von Abbruch unterscheiden. Für den Anwender wäre noch eine aussagekräftigere Exception gut, also indem Du sie an der passenden Stelle abfängst und eine benutzerdefinierte wirfst.
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Donnerstag 25. April 2019, 09:28
von PythonMan2019
Hallo
Danke. Hab es nun mit try: except: hinbekommen!
Grüße
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Donnerstag 25. April 2019, 09:41
von __blackjack__
Wobei das ziemlich sicher schlecht/falsch gelöst ist. Selbst wenn `TclError` explizit behandelt wird, sollte man einfach nicht den Wert abfragen wenn das Fenster dazu bereits zerstört ist. Sauberer wäre es sich für das Schliessen des Fensters über das Kreuz in der Fensterleiste (oder auch auf anderen Wegen) zu registrieren und das wie ein Abbrechen des Eingabedialogs zu behandeln. Also so wie `tkinter.simpledialog.Dialog` das macht. Was man dann vielleicht auch gleich benutzen könnte, bevor man das Rad neu erfindet. Oder vielleicht sogar eine der `ask*()`-Funktionen aus dem Modul, falls die ausreichen.
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Freitag 26. April 2019, 22:24
von PythonMan2019
Hallo
ich versuche gerade den OK Button mit der "Enter" Taste zu verbinden, aber irgendwie klappt es nicht

Was mache ich falsch? ich möchte nur mit der Enter Taste das Fenster wieder schliessen!
Code: Alles auswählen
import Tkinter as tk
master = tk.Tk()
def onReturn(*event):
#xGet = entry.get()
#print xGet
master.destroy
entry = tk.Entry(master,bd=1)
entry.pack()
button = tk.Button(master, text='Enter', command=onReturn)
button.pack()
button.focus_set()
master.bind('<Return>', onReturn)
tk.mainloop()
Grüsse
Stefan
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Samstag 27. April 2019, 11:55
von PythonMan2019
Kann mir da keiner weiterhelfen?
Gruss
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Samstag 27. April 2019, 12:38
von __deets__
Ich sehe schonmal einen Fehler im onReturn. Da denkst du nur du rufst auf, tust es aber nicht.
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Samstag 27. April 2019, 12:47
von PythonMan2019
Verstehe nicht was du meinst?
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Samstag 27. April 2019, 12:47
von PythonMan2019
Verstehe nicht was du meinst?
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Samstag 27. April 2019, 12:50
von __deets__
Ah, Wort vergessen. Du rufst destroy nicht auf. Dazu fehlen die Klammern.
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Samstag 27. April 2019, 13:11
von wuf
Hi PythonMan2019
So sollte es funktionieren:
Code: Alles auswählen
import Tkinter as tk
def onReturn(event=None):
#xGet = entry.get()
#print xGet
master.destroy()
master = tk.Tk()
entry = tk.Entry(master, bd=1)
entry.pack()
button = tk.Button(master, text='Enter', command=onReturn)
button.pack()
button.focus_set()
master.bind('<Return>', onReturn)
master.mainloop()
Gruss wuf

Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Samstag 27. April 2019, 17:08
von PythonMan2019
Hallo
Danke für die Korrektur. Mit dem code klappts.
Aber sobald ich diesen zeiler hinzufüge
Code: Alles auswählen
tk.Label(master, text="Checkpoints / Variant:\n ",font = ("arial", 11, "bold")).grid (row=0, column=0, columnspan=2, sticky=tk.W)
Geht das popup in die knie. Es öffnet sich mit leerem inhalt und lässt sich nicht mehr schliessen. Ich muss dann das script killen.
Re: Tkinter Popup Fenster richtig schliessen?
Verfasst: Samstag 27. April 2019, 20:31
von wuf
Hi PythonMan2019
So funktioniert es wieder. Beim mischen von
pack &
grid ist Vorsicht geboten:
Code: Alles auswählen
import Tkinter as tk
def onReturn(event=None):
#xGet = entry.get()
#print xGet
master.destroy()
master = tk.Tk()
tk.Label(master, text="Checkpoints / Variant:\n ",font = ("arial", 11, "bold")
).pack()
entry = tk.Entry(master, bd=1)
entry.pack()
button = tk.Button(master, text='Enter', command=onReturn)
button.pack()
button.focus_set()
master.bind('<Return>', onReturn)
master.mainloop()
Gruss wuf
