Seite 1 von 1

Trace in Verbindung mit Entry-Variablen

Verfasst: Freitag 20. März 2020, 08:45
von tryanderror
Hallo,

ich bin gerade dabei bei einer Gui von mir ein bisschen aufzuräumen und Zeilen zu sparen, bzw. auch Optimierungen zu machen um If-Abfragen zu vereinfachen.
Konkret bin ich momentan dabei Entry-Felder anzulegen und will den Input in diesen Felder Überwachen bzw. soll, wenn ungewollte Zeichen eingelesen werden diese Entfernt werden. Auch zu lange Eingaben sollen verhindert werden.

Da bin ich auf die Tolle Trace-Funktion gestoßen und habe auch mein Ziel erreicht nun aber wollte ich das bisschen kleiner aufschreiben um Übersicht zu behalten.

Also hier erstmal das was so wie es ist Funktioniert:

Code: Alles auswählen

textvars = []
self.entrys = []

for element in range(4):
    textvars.append( tkinter.StringVar() )
    self.entrys.append( tkinter.Entry( width=5, textvariable=textvars[element], justify="center") )

textvars[0].trace("w", lambda name, index, mode, var=textvars[0]: self.clean_input(self.entrys[0].get(),textvars[0]._name))
textvars[1].trace("w", lambda name, index, mode, var=textvars[1]: self.clean_input(self.entrys[1].get(),textvars[1]._name))
textvars[2].trace("w", lambda name, index, mode, var=textvars[2]: self.clean_input(self.entrys[2].get(),textvars[2]._name))
textvars[3].trace("w", lambda name, index, mode, var=textvars[3]: self.clean_input(self.entrys[3].get(),textvars[3]._name))

def clean_input(self, value, var):
    print(value, var)

Man kann sich schon denken was ich wohl im Quelcode reduzieren wollte...
Ich wollte ledeglich die For um eine Zeile ergänzen, damit ich alles in einem Block fertig mache.

Code: Alles auswählen

for element in range(4):
    textvars.append( tkinter.StringVar() )
    self.entrys.append( tkinter.Entry( width=5, textvariable=textvars[element], justify="center") )
    textvars[element].trace("w", lambda name, index, mode, var=textvars[element]: self.clean_input(self.entrys[element].get(),textvars[element]._name))
Resultat ist aber, dass nun Trace nur an dem letzten Entry hängt(auslösen tut es bei jedem Entry), ich habe die einzelnen Entrys auch nochmal mit print ausgeben lassen um sicher zu stellen, dass diese auch alle ihre eigene Variable haben. Ich bekomme egal in welches Feld ich schreibe immer als Variable PY_VAR3, und die Value dieser... Übersehe ich etwas oder verwende ich Trace falsch?

Re: Trace in Verbindung mit Entry-Variablen

Verfasst: Freitag 20. März 2020, 09:22
von __deets__
Du machst dir das Leben unnoetig schwer durch den permanenten Zugriff auf textvars[element]. Weise die neue StringVar lieber einem Namen zu, den du dann spaeter in textvars steckst. Gleiches gilt fuer das Entry.

Und dann uebergibst du BEIDES gebunden an einen Namen ans lambda, und verwendest das. Denn da liegt dein Fehler: auch wenn du var bindest im Lamba, du benutzt es nicht. Stattdessen greifst due immer ueber die Datenstruktur zu, und den Index element. Der immer auf 3 zeigt, weil das der letzte vergebene Wert war.

Re: Trace in Verbindung mit Entry-Variablen

Verfasst: Freitag 20. März 2020, 09:51
von Sirius3
Speichere die textvars auch in self.
Wenn Du textvars hast, brauchst Du eigentlich das Entry gar nicht mehr wissen.
Benutze functools.partial statt lambda.

Code: Alles auswählen

for element in range(4):
    textvar = tkinter.StringVar()
    tkinter.Entry(width=5, textvariable=textvar, justify="center").pack()
    textvar.trace("w", partial(self.clean_input, textvar))
    self.textvars.append(textvar)

def clean_input(self, textvar):
    print(textvar, textvar.get())

Re: Trace in Verbindung mit Entry-Variablen

Verfasst: Freitag 20. März 2020, 10:05
von __blackjack__
@tryanderror: Das `_name`-Attribut gehört nicht zur öffentlichen API von `StringVar`, da solltest Du nicht drauf zugreifen. Das bedeuten einzelne führende Unterstriche bei Attributnamen.