Python Forum

Full Version: How Does Entry Verification Work?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have the following Entry defined:
phone=tk.Entry(top,width=12,justify=tk.LEFT)
phone.grid(row=rw,column=1,pady=5,sticky=tk.W)
reg=top.register(validatePhone)
phone.config(validate='key',validatecommand=(reg,'%P'))
This is 'reg':
def validatePhone(num):
    pattern=re.compile('\d{3}-\d{3}-\d{4}')
    if (pattern.search(num)):
        print('true')
    else:
        print('false')
    return(pattern.search(num))
According to my documentation, the validate routine, 'reg', is supposed to be called every keystroke that changes the field. This does not seem to be the case. It is called only once. If I enter the first character, right or wrong, that character does not display in the field. The string 'false' is output. If I enter a 2nd character, it shows up but 'reg' apparently is never called again. Nothing seems to happen even when 'reg' returns false. Obviously I'm missing how to use entry validation and the documentation is of little help. TIA.
The problem with only calling once appears to be related to returning None. I changed you callback to this and it is called for each keystroke.
def validatePhone(num):
    print('called')
    pattern=re.compile('\d{3}-\d{3}-\d{4}')
    ok =  pattern.search(num)
    print('got here', num, ok)
    return True if ok else False
To verify I tried both of these for validate. Returning None behaves as you saw. Called only once then validation no longer used. Returning False runs each time the key is pressed.
def validateFalse(num):
    print(num)
    return False

def validateNone(num):
    print(num)
    return None
So your validation function needs to return True or False. But you still have a problem. The only way you can enter a phone number is using copy/paste. Typing will never match your pattern because 1 digit does not match your pattern and typing in "555-867-5309" requires you first type "5".

I don't know how to write a regex that would match '5', '55', '555' and '555-' but not '55-', '5-' or '-'. This works.
def validatePhone(num):
    pattern = 'ddd-ddd-dddd'
    if len(num) > len(pattern):
        return False
    for digit, chr in zip(num, pattern):
        if chr == 'd':
            if not digit.isdigit():
               return False
        elif digit != chr:
            return False
    return True
Thanks but I stumbled on a solution that works. Rather than register the validation routine I simply use the validation as a command on the button:

submitButton=tk.Button(top,text='Submit',command=validatePhone)
Thus the only time I try to validate is when the submit button is clicked. My validate probably does not need everything I am doing in it but it helps for debugging.
def validatePhone():
    num=phone.get()
    print(num)
    pattern=re.compile('\d{3}-\d{3}-\d{4}')
    if (pattern.search(num)):
        print('true')
        top.quit()
    else:
        phone.configure(background='Red')
        print('false')
    return(pattern.search(num))
When 'top.quit' is called it lets the script proceed with processing the tkinter data.