Search code examples
tkinterbackspacetkinter-entry

Tkinter - validatecommand + backspace


I'm trying to make an Entry with a limit of 16 characters. So far I have something like this:

import tkinter as tk

rt = tk.Tk()

def tr_input():
    a = e['textbox']
    b = a.get()
    print(b)
    if "\b" in b:
        return True
    if "\n" in b:
        calculate()
    elif len(b)>16:
        return False
    return True

e = { "textbox":tk.Entry(rt,validate = "all",validatecommand=tr_input) }

calculate() performs a calculation on numbers in the Entry, and displays it in another Label

It works fine, and prevents any further characters from being entered after the 16th one. However, it also prevents characters from being removed via backspace, and I can't figure out how to... not have it do that.
Does anyone know how I can fix this?

Edit: Specifically, I need to be able to find out if the last button pressed was backspace


Solution

  • You can have the validatecommand pass in information so that you don't have to detect any keys. For example, you can tell it to pass in the value that would be in the widget if the edit is allowed. You can check that value against the desired length without having to know if the user is adding or removing characters, or whether they typed the characters or pasted them in.

    You do this by first registering your command, along with arguments to be passed to your command. For example:

    vcmd = (rt.register(tr_input), '%d', '%P', '%s')
    

    You then pass this vcmd to the validatecommand option:

    e = { "textbox":tk.Entry(rt,validate = "all",validatecommand=vcmd) }
    

    Finally, modify your tr_input function to accept these arguments:

    def tr_input(d, P, s):
        # d = type of action (1=insert, 0=delete, -1 all others)
        # P = value of entry if edit is allowed
        # s = value of entry prior to allowing the edit
        print("tr_input: d='%s' P='%s' s='%s'" % (d,P,s))
        if len(P) > 16:
            return False
        return True
    

    For more information see this answer: https://stackoverflow.com/a/4140988/7432