I'm working on validating some entry widgets, going through various posts here on SO and google. Have modified Bryan O. code to almost work. When the entry text is one digit, validation fails - why?? 2 or more, it succeeds.
My change is checking for numbers instead of lower case letters. The original code does, of course, work as advertised.
import Tkinter as tk
def onvalidate(d,i,P,s,S,v,V,W):
# only lowercase is valid
# valid = (P.lower() == P)
valid = P.isdigit()
print 'P is:', type(P), P
print 'valid is:', valid
# set red background if invalid
newcolor = 'red' if not valid else default_color
root.nametowidget(W).configure(background=newcolor)
return valid
def oninvalid(d,i,P,s,S,v,V,W):
#called if widget is invalid
widget = root.nametowidget(W)
# S is the character that *would* have been
# inserted or deleted, but won't because it is invalid
# So we do it ourselves
if S:
if d=='0':
widget.delete(i, len(S))
elif d=='1':
widget.insert(i, S)
# Changing the text clears the 'validate' value
# so we have to reset it
widget.after_idle(lambda W,v: root.nametowidget(W).configure(validate=v), W, v)
root = tk.Tk()
valhook = (root.register(onvalidate), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
invhook = (root.register(oninvalid), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
entry = tk.Entry(root, validate="key", validatecommand=valhook, invalidcommand=invhook)
default_color = entry.cget('background')
entry.pack()
Method 2 (simpler code): works only for first char entered, additional fails. I understand S is current char, P is for allowed edit, but I'm pretty sure I want to be checking S here. Why doesn't it work for everything entered in the field??
import Tkinter as tk
def OnValidate(d, i, P, s, S, v, V, W):
print "OnValidate:"
print "d='%s'" % d
print "i='%s'" % i
print "P='%s'" % P
print "s='%s'" % s
print "S='%s'" % S
print "v='%s'" % v
print "V='%s'" % V
print "W='%s'" % W
# only allow if the string is lowercase
# return (S.lower() == S)
print 'S is:', S, type(S)
if S.isdigit():
print 'Check:', S.isdigit()
return S
else:
pass
root = tk.Tk()
vcmd = (root.register(OnValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
entry = tk.Entry(root, validate="key",
validatecommand=vcmd)
entry.pack()
root.mainloop()
Your validation function must return either True
or False
, which tells tkinter whether to allow the edit or not. If it returns anything else, the validation will be turned off.
if S.isdigit():
return True
else:
False