OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

Tkinter validation triggers an unexpected function causing application to hang

  • Thread starter Thread starter Psionman
  • Start date Start date
P

Psionman

Guest
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.

Neither entry can be empty and I do not have default values for either.

How can I fix this?

Code:
import tkinter as tk
from tkinter import ttk


class MainFrame():
    def __init__(self):
        self.root = tk.Tk()

        self.entry_value_a = tk.StringVar(value='')
        self.entry_value_b = tk.StringVar(value='')

        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() == '':
            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() == '':
            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()
<p>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 <em>False</em> from the function <em>validate_b</em>, the application hangs.</p>
<p>Neither entry can be empty and I do not have default values for either.</p>
<p>How can I fix this?</p>
<pre><code>import tkinter as tk
from tkinter import ttk


class MainFrame():
def __init__(self):
self.root = tk.Tk()

self.entry_value_a = tk.StringVar(value='')
self.entry_value_b = tk.StringVar(value='')

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() == '':
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() == '':
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()
</code></pre>
 

Latest posts

S
Replies
0
Views
1
Sergey Bakaev Rettley
S
Top