This code
from tkinter import *
root = Tk()
test = StringVar()
test.set('')
passarg = 'hello'
test.trace('w', lambda passed = passarg: checkvar(passed))
testEntry = Entry(root, textvariable = test)
testEntry.pack(fill = X)
root.mainloop()
def checkvar(passedarg, *args):
print(passedarg)
produces a TypeError: (lambda)() takes 1 positional argument but 3 were given
when the callback is called, even though I already use *args
in the function definition.
Alternatively, I've tried adding some fake arguments to get to 3, but then the callback doesn't get any of the passed arguments at all:
from tkinter import *
def checkvar(passedarg, *args):
print(passedarg)
print(args)
root = Tk()
test = StringVar()
test.set('')
passarg = 'hello'
test.trace('w', lambda passed = passarg, a = 1, b = 2: checkvar(passed, a, b))
testEntry = Entry(root, textvariable = test)
testEntry.pack(fill = X)
root.mainloop()
prints
PY_VAR0
('', 'w')
whenever I write in the entry field.
I need a callback function with arguments for a bigger program, so is there any way to do that?
Clarification: The bigger program has many entry fields of varying max input lengths, all of which are checked to only contain a subset of ASCII characters (with a regex ^[0-9A-Za-z\.\-\+]+$
). The underlying idea was that I could have a general validate function that would be passed a tkintervar (to check the characters) and an integer length in a trace, instead of creating a separate function for each length limit.
Your lambda
is what must accept the arguments and pass them on to your function, since it is the lambda that is being called when the variable changes. The simplest fix to make your code work is to change the lambda to this:
test.trace('w', lambda *args, passed = passarg: checkvar(passed, *args))
You say you're using this for input validation. Are you aware that the entry widget has a built-in feature for entry validation? See Interactively validating Entry widget content in tkinter