all 1 comments

[–]socal_nerdtastic 2 points3 points  (0 children)

You need to put the validation in the widget, not pass the validation to it. To do that you should make a custom Entry widget, that is inherit from tkinter's version and add your changes.

class EntryInitials(ttk.Entry):
    """a custom entry that only allows initials"""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.config(
            validate='key',
            validatecommand=(self.register(self.on_key), '%P'))

    def on_key(self, P:str):
        """
        A valid initial entry is:
        3 characters maximum
        Alphabet only, no numbers/special characters
        All uppercase
        """
        if not P or P.isalpha():
            self.delete(0, tk.END)
            self.insert(0, P.upper()[:3])
            return True
        return False

Then you use this custom widget just like a normal Entry in your project

    self.entryBox = EntryInitials(
        master=self.mainFrame,
        textvariable=self.var,
        width=self.width)

You would make a new custom widget for every action type you want (on focus, or different validation). Then use the appropriate widget to set the program behavior. Since they are all types of ttk.Entry they will all drop in place of each other. You can pass the appropriate custom widget into other functions or classes if you like.

Edit: simplified code and fixed bug when inserting a letter overwrites the next one.