Python Forum
[Tkinter] How Does Entry Verification Work?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] How Does Entry Verification Work?
#1
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.
Reply
#2
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
Reply
#3
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.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Transfer Toplevel window entry to root window entry with TKinter HBH 0 4,483 Jan-23-2020, 09:00 PM
Last Post: HBH
  [Tkinter] how to get the entry information using Entry.get() ? SamyPyth 2 3,516 Mar-18-2019, 05:36 PM
Last Post: woooee

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020