La risposta corretta è, usa l' validatecommandattributo del widget. Sfortunatamente questa caratteristica è gravemente poco documentata nel mondo Tkinter, sebbene sia sufficientemente documentata nel mondo Tk. Anche se non è ben documentato, ha tutto il necessario per eseguire la convalida senza ricorrere a binding o variabili di tracciamento o modificare il widget dall'interno della procedura di convalida.
Il trucco è sapere che puoi fare in modo che Tkinter passi valori speciali al tuo comando di convalida. Questi valori forniscono tutte le informazioni necessarie per decidere se i dati sono validi o meno: il valore prima della modifica, il valore dopo la modifica se la modifica è valida e molti altri bit di informazioni. Per usarli, però, devi fare un po 'di voodoo per far passare queste informazioni al tuo comando di validazione.
Nota: è importante che il comando di convalida restituisca Trueo False. Qualsiasi altra cosa provocherà la disattivazione della convalida per il widget.
Ecco un esempio che consente solo il minuscolo (e stampa tutti quei valori funky):
import tkinter as tk
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
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)
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()
Per ulteriori informazioni su ciò che accade dietro le quinte quando si chiama il registermetodo, vedere tkinter di convalida dell'input