正解は、validatecommand
ウィジェットの属性を使用することです。残念ながら、この機能はTkinterの世界では十分に文書化されていますが、Tkinterの世界では十分に文書化されていません。十分に文書化されていませんが、バインディングや変数のトレースに頼ったり、検証手順内からウィジェットを変更したりすることなく、検証を行うために必要なすべてが揃っています。
秘訣は、Tkinterにvalidateコマンドに特別な値を渡させることができることを知ることです。これらの値は、データが有効かどうかを判断するために知っておく必要のあるすべての情報を提供します。編集前の値、編集が有効な場合は編集後の値、およびその他のいくつかの情報です。ただし、これらを使用するには、この情報をvalidateコマンドに渡すために少しブードゥーを行う必要があります。
注:検証コマンドがまたはのいずれTrue
かを返すことが重要ですFalse
。それ以外の場合は、ウィジェットの検証がオフになります。
小文字のみを許可する(そしてそれらすべてのファンキーな値を出力する)例を次に示します。
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()
register
メソッドを呼び出したときに内部で何が起こるかについての詳細は、入力検証tkinterを参照してください。