Search code examples
pythonpython-3.xtkinterfocustkinter-entry

tkinter: Move focus to next widget when entry widget is full without losing keystroke


this is my first question on here so sorry if im doing things wrong.

I'm creating a entry class that will validate the length of the input, then focus the next widget. The below code does this, but it triggers the focus change on the keypress AFTER the desired length, which causes us to lose that keypress

Example: if you type 123456789 into the first entry box, the end result will be 1234 in entry box 1, and 6789 in entry box 2

import tkinter as tk

class ValidateEntry(tk.Frame):

    def __init__(self, parent, width=20, txt=None): 
        tk.Frame.__init__(self, parent)
        self.width = width
        vcmd = (self.register(self.validate), '%i', '%S', '%d', '%P')
        self.entry = tk.Entry(self, width=self.width, validate='key', vcmd=vcmd)
        if txt is not None:
            self.entry.insert('end', txt)
        self.entry.pack()

    def validate(self, i, S, d, P):# i = index, S = insert character, d = action, P = entry value
        if len(P)-1 == self.width and d != 0:
            self.entry.tk_focusNext().focus()
            return False
        return True

root = tk.Tk()
entry1 = ValidateEntry(root, width=4)
entry2 = tk.Entry(root, width=8)
entry1.pack()
entry2.pack()
root.mainloop()

I cannot figure out a way to change focus and keep the 5th keypress in the example above


Solution

  • At the 4th keypress, you want to accept the key (so return true) and change focus. so simply change the validate function to:

    def validate(self, i, S, d, P):# i = index, S = insert character, d = action, P = entry value
        if len(P) == self.width and d != 0:
            self.entry.tk_focusNext().focus()
        return True