Search code examples
pythonvalidationuser-interfacetkintertkinter-entry

How do I validate text entry to match an expected input?


Part of my program asks the user for their name and class (as in high school class). In the first text entry I would like the program to only accept a name of say no more than 10 characters but more importantly LETTERS ONLY. For the second text entry the user has to enter their class - the program should expect one of the following: 5A1, 5A2, 5B1, 5B2, 5C1, 5C2 ... 6C1, 6C2.

How to do these validations?

class Enter_Name_Window(tk.Toplevel):
'''A simple instruction window'''
def __init__(self, parent):
    tk.Toplevel.__init__(self, parent)
    self.text = tk.Label(self, width=40, height=2, text= "Please enter your name and class." )
    self.text.pack(side="top", fill="both", expand=True)


    name_var = StringVar()
    def validate_enter_0():
        self.Enter_0.config(state=(NORMAL if name_var.get() else DISABLED))
        print("validate enter worked")
    name_var.trace('w', lambda name, index, mode: validate_enter_0)
    enter_name = Entry(self, textvariable=name_var)
    enter_name.pack()
    enter_name.focus_set()


    def callback():
        self.display_name = tk.Label(self, width=40, height=2, text = "Now please enter your tutor group.")
        self.display_name.pack(side="top", fill="both", expand=True)


        tutor_var = StringVar()
        def validate_enter_2():
            self.Enter_0_2.config(state=(NORMAL if tutor_var.get() else DISABLED))
            print("validate enter worked")
        tutor_var.trace('w', lambda name, index, mode: validate_enter_0_2)
        tutor = Entry(self, textvariable=tutor_var)
        tutor.pack()
        tutor.focus_set()

        self.Enter_0.config(state="disabled")

        self.Enter_0_2 = Button(self, text="Enter", width=10, command=self.destroy)
        self.Enter_0_2.pack()


    self.Enter_0 = Button(self, text="Enter", width=10, command=callback)
    self.Enter_0.pack()

Solution

  • For your first check

    import string
    
    if len(name) > 10 or any(l not in string.ascii_letters for l in name):
        # reject
    

    for your second

    if cls not in ["5A1", "5A2", ...]:
        # reject
    

    or you could do something a bit more complex:

    def validate_class(cls):
        if (len(cls) != 3 or 
            int(cls[0]) not in [5, 6] or
            cls[1] not in ["A", "B", "C"] or 
            int(cls[2]) not in [1, 2]):
            return False
        return True
    

    This expresses a more general rule for what a valid class cls is.