pythonvalidationtkintertkinter-entrydata-entry

TTK Enty validation issue


I am writing my very first GUI app with Py and Tkinter (Ttkinter). I want to be sure that the user can write only digits, "," and "." in the entries field. So far I did this but I have a couple of issues:

  1. I am not able to make it accept "," and ".";

  2. Using this method I can't use the clean functions that I wrote to clean the entries widget.

#Validation function
def dig_check(input):
    if input.isdigit():
        print(input)
        return True
    
    else:
        print(input)
        return False

#Clean function
def clean_calc():
    r_top_entry.delete(0,END)
    r_bot_entry.delete(0,END)
    p_thick_entry.delete(0,END)
    b_angle_deg_entry.delete(0,END)
    b_angle_m_entry.delete(0,END)
    b_angle_s_entry.delete(0,END)
    b_height_entry.delete(0,END)

    De_label.config(text="-")
    Dm_label.config(text="-")
    Di_label.config(text="-")
    de_label.config(text="-")
    dm_label.config(text="-")
    di_label.config(text="-")

    deg_value.config(text="-")
    min_value.config(text="-")
    sec_value.config(text="-")

#Entry widget example
r_top_entry = ttk.Entry(blank_frame, width=10, validate="key", validatecommand=(root.register(dig_check),"%P"))

Can someone help me and explain me what am I doing wrong?


Solution

  • You'll need to modify your validator to accept the other characters

    def dig_check(usr_input):
        # accept digits, '.', ',', or empty values
        char = usr_input[-1]  # get the latest character added to the Entry
        if char.isdigit() or char in '.,' or char == '':
            return True
        return False
    

    It's good to accept empty values as well so the user can delete the contents of the Entry. You'll need to check for these after the fact, but if you don't catch them here your Entry will always have to have some value, which is probably not what you want.

    Note that this will also permit multiple consecutive '.' and ',' characters, and won't dictate where those characters are allowed. For something more stringent, you'll probably want to look at RegEx.

    Also, I've changed input to usr_input since input is a reserved word (it's a function)


    If you want to be more prescribed in your validation (and generally, you should!), you can do something like this:

    import re
    
    
    def dig_check(usr_input):
        pattern = re.compile(r'^\d+(?:,?\d*)*.?\d*$|^$')
        if re.search(pattern, user_input):
            return True
        return False
    

    Bear in mind that the RegEx pattern here isn't exhaustive, and can allow for things like multiple consecutive commas...I'm just demonstrating a point!