Die richtige Antwort lautet: Verwenden Sie das validatecommand
Attribut des Widgets. Leider ist diese Funktion in der Tkinter-Welt stark unterdokumentiert, obwohl sie in der Tkinter-Welt ausreichend dokumentiert ist. Obwohl es nicht gut dokumentiert ist, bietet es alles, was Sie für die Validierung benötigen, ohne auf Bindungen oder Ablaufverfolgungsvariablen zurückgreifen oder das Widget innerhalb des Validierungsverfahrens ändern zu müssen.
Der Trick besteht darin, zu wissen, dass Tkinter spezielle Werte an Ihren Validierungsbefehl übergeben kann. Diese Werte geben Ihnen alle Informationen, die Sie wissen müssen, um zu entscheiden, ob die Daten gültig sind oder nicht: den Wert vor der Bearbeitung, den Wert nach der Bearbeitung, wenn die Bearbeitung gültig ist, und mehrere andere Informationen. Um diese zu verwenden, müssen Sie jedoch ein wenig Voodoo machen, um diese Informationen an Ihren Validierungsbefehl zu übergeben.
Hinweis: Es ist wichtig, dass der Validierungsbefehl entweder True
oder zurückgibt False
. Alles andere führt dazu, dass die Validierung für das Widget deaktiviert wird.
Hier ist ein Beispiel, das nur Kleinbuchstaben zulässt (und alle diese funky Werte druckt):
import tkinter as tk # python 3.x
# import Tkinter as tk # python 2.x
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# valid percent substitutions (from the Tk entry man page)
# note: you only have to register the ones you need; this
# example registers them all for illustrative purposes
#
# %d = Type of action (1=insert, 0=delete, -1 for others)
# %i = index of char string to be inserted/deleted, or -1
# %P = value of the entry if the edit is allowed
# %s = value of entry prior to editing
# %S = the text string being inserted or deleted, if any
# %v = the type of validation that is currently set
# %V = the type of validation that triggered the callback
# (key, focusin, focusout, forced)
# %W = the tk name of the widget
vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
self.text = tk.Text(self, height=10, width=40)
self.entry.pack(side="top", fill="x")
self.text.pack(side="bottom", fill="both", expand=True)
def onValidate(self, d, i, P, s, S, v, V, W):
self.text.delete("1.0", "end")
self.text.insert("end","OnValidate:\n")
self.text.insert("end","d='%s'\n" % d)
self.text.insert("end","i='%s'\n" % i)
self.text.insert("end","P='%s'\n" % P)
self.text.insert("end","s='%s'\n" % s)
self.text.insert("end","S='%s'\n" % S)
self.text.insert("end","v='%s'\n" % v)
self.text.insert("end","V='%s'\n" % V)
self.text.insert("end","W='%s'\n" % W)
# Disallow anything but lowercase letters
if S == S.lower():
return True
else:
self.bell()
return False
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
Weitere Informationen darüber, was beim Aufrufen der register
Methode unter der Haube passiert, finden Sie unter Eingabeüberprüfung tkinter