I have a tkinter app. On load the focus is set to the first entry widget (self.entry_a). When I tab out of the entry (self.entry_a) for the first time it triggers the validation for the second entry (self.entry_b). This means that if I return False from the function validate_b, the application hangs
How can I fix this?
import tkinter as tk
from tkinter import ttk
class MainFrame():
def __init__(self):
self.root = tk.Tk()
self.entry_value_a = tk.StringVar(value='0')
self.entry_value_b = tk.StringVar(value='0')
self.root.geometry('400x300')
main_frame = self._main_frame()
main_frame.grid(row=0, column=0, sticky=tk.EW)
self.root.mainloop()
def _main_frame(self) -> tk.Frame:
frame = ttk.Frame(self.root)
frame.columnconfigure(1, weight=1)
valid_command_a = (self.root.register(self.validate_a), '%P')
invalid_command_a = (self.root.register(self.on_invalid_a),)
self.entry_a = ttk.Entry(frame, textvariable=self.entry_value_a)
self.entry_a.config(
validate='focusout',
validatecommand=valid_command_a,
invalidcommand=invalid_command_a
)
self.entry_a.grid(row=0, column=0)
self.entry_a.focus_set()
self.entry_a.select_range(0, 999)
valid_command_b = (self.root.register(self.validate_b), '%P')
invalid_command_b = (self.root.register(self.on_invalid_b),)
self.entry_b = ttk.Entry(frame, textvariable=self.entry_value_b)
self.entry_b.config(
validate='focusout',
validatecommand=valid_command_b,
invalidcommand=invalid_command_b
)
self.entry_b.grid(row=1, column=0)
self.label_error = ttk.Label(frame, foreground='red')
self.label_error.grid(row=2, column=0, sticky=tk.W, padx=5)
return frame
def validate_a(self, event: object = '') -> bool:
print('a triggered')
self.label_error['text'] = ''
if self.entry_value_a.get() == '0':
return False
return True
def on_invalid_a(self):
self.label_error['text'] = 'Invalid entry a'
self.entry_a.focus_set()
self.entry_a.select_range(0, 999)
def validate_b(self, event: object = '') -> bool:
print('b triggered')
self.label_error['text'] = ''
if self.entry_value_b.get() == '0':
return # False
return True
def on_invalid_b(self):
self.label_error['text'] = 'Invalid entry b'
self.entry_b.focus_set()
self.entry_b.select_range(0, 999)
if __name__ == '__main__':
MainFrame()