I am trying to use built-in input validation of Tkinter's Entry widget but I can't figure out why I receive a TypeError when entry validation is triggered. (regardless of what kind of event triggers the validation). In the simple code below, I am trying to validate only numerical input from the user. Alphabetical characters must disable the Apply button. But as soon as you enter ANY character, a "TypeError: 'str' object is not callable" is raided. Any ideas why?!
from tkinter import *
from tkinter import ttk
root = Tk()
entry_string = StringVar()
entry_field = ttk.Entry(root, textvariable=entry_string, validate='key')
apply_button = ttk.Button(root, text='Apply', state='normal')
entry_field.grid(column = 0 , row = 0)
apply_button.grid(column = 0 , row = 1)
def validate(entry):
if str(entry).isnumeric():
apply_button.config(state = 'normal')
return TRUE
else:
return FALSE
def on_invalid():
apply_button.config(state='disabled')
vcmd = (root.register(validate(entry_string), '%P'))
ivcmd = (root.register(on_invalid()),)
entry_field.config(validatecommand=vcmd, invalidcommand=ivcmd)
root.mainloop()
CodePudding user response:
Issue
- Format for the validatecommand argument should be
(register(f), s1, s2, ...)
. Your is currently(register(f, s1, s2, ...))
. - You are passing the returned value of
validate
function toregister
, instead you need pass the function itself.
Reference
I highly recommend you to read this page from docs
Fix
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
entry_string = tk.StringVar()
entry_field = ttk.Entry(root, textvariable=entry_string, validate='key')
apply_button = ttk.Button(root, text='Apply', state='normal')
entry_field.grid(column = 0 , row = 0)
apply_button.grid(column = 0 , row = 1)
def validate(value):
if str(value).isnumeric():
apply_button.config(state = 'normal')
return tk.TRUE
else:
return tk.FALSE
def on_invalid():
apply_button.config(state='disabled')
vcmd = (root.register(validate), '%P')
ivcmd = (root.register(on_invalid),)
entry_field.config(validatecommand=vcmd, invalidcommand=ivcmd)
root.mainloop()