Search code examples
validationtkintertkinter-entry

Entry validation fails when replacing spaces with empty strings


I am not sure why validation stops working after I end up replacing spaces in a string. The validation works fine for most things I need. It allows for only numbers and up to 10 of them while also allowing for back spaces and highlighting all and back spacing. It also works once when pasting in values that contain spaces.

For example if I try to paste 12 34 into the entry field it will correctly change the value to 1234 but after that validation just stops working.

Update:

It appears that validation stops working after entry.delete() though I still am not sure how to correct this. I have tried to redefine the validation but that did not work.

import tkinter as tk


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.vcmd = (self.register(self.validate), '%d', '%P', '%s')
        self.entry = tk.Entry(self, validate='key', validatecommand=self.vcmd)
        self.entry.pack()

    def validate(self, *a):
        b = a[1].replace(' ', '')
        if b.isdigit() and len(b) <= 10 or ((b == '' or b < a[2]) and a[0] == '0'):
            if ' ' in a[1]:
                x = a[1]
                x = x.replace(' ', '')
                self.entry.delete(0, 'end')
                self.entry.insert(0, x)
            return True

        else:
            return False

App().mainloop()

Update:

I managed to get it working by deleting the entry field and redefining it and its validation after inserting the new string. But this seams like the wrong way to do this.

import tkinter as tk


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.vcmd = (self.register(self.validate), '%d', '%P', '%s')
        self.entry = tk.Entry(self, validate='key', validatecommand=self.vcmd)
        self.entry.pack()

    def validate(self, *a):
        b = a[1].replace(' ', '')
        if b.isdigit() and len(b) <= 10 or ((b == '' or b < a[2]) and a[0] == '0'):
            if ' ' in a[1]:
                x = a[1]
                x = x.replace(' ', '')
                self.entry.destroy()
                self.entry = tk.Entry(self)
                self.entry.insert(0, x)
                self.entry.config(validate='key', validatecommand=self.vcmd)
                self.entry.pack()
            return True
        else:
            return False

App().mainloop()

Solution

  • I am not sure why validation stops working after I end up replacing spaces in a string. The validation works fine for most things I need.

    It stops working because that's how it is designed to work. If you try to modify the data from within the validation function, the validate option is automatically reset to "none".

    This is what the official tcl/tk documentation says:

    The validate option will also set itself to none when you edit the entry widget from within either the validateCommand or the invalidCommand.

    You will need to reset the validate option in the case where you modify the widget from within the validation function.