I am a newbie on Python3 and trying tkinter for first time, I recently answered to 
that ask for inputs.
first 3 Entry row are validated by callback_int that allows only int digits while last 2 Entry rows use callback_str that allow both floats like 1.5 or 0.5 and fractions like 1/7 or 5/7.
My question (sorry it took so long) is:
is there a way to pass function arguments to callback like callback(typez = str)
so that I could shorten my code using only one callback function that acts differently for my int and string values ? If I use reg_int = mainwindow.register(callback_int(input,typez='popo')) I got
line ...
if input.isdigit():
AttributeError: 'function' object has no attribute 'isdigit'
I am guessin the problem is in :
reg_int = mainwindow.register(callback_int(input,typez='popo')) #AttributeError: 'function' object has no attribute 'isdigit'
reg_str = mainwindow.register(callback_str('pipi'))
but wasnt able to find anythiong useful , or maybe my approach is in the wrong direction
CodePudding user response:
This uses the lambda statement to pass either "str" or "int" to the typez argument in callback(), so that callback() knows what type the input is. Here is the full code based on my first comment above:
import tkinter as tk
from tkinter import IntVar,StringVar
###############################################################################
def callback(input,typez=None):
if typez == "int":
if input.isdigit():
# print(input)
return True
elif input == "":
# print(input)
return True
else:
print(input)
return False
if typez == "str":
if len(input) >=1 and input[0] == '/':
return False
if all([s.isdigit() or s =='/' for s in input]) and input.count('/') <= 1:
# print([s.isdigit() or s =='/' for s in input])
# print(input)
return True
elif all([s.isdigit() or s =='.' for s in input]) and input.count('.') <= 1:
# print([s.isdigit() or s =='.' for s in input])
# print(input)
return True
else:
print('no valid input : ',input)
return False
def mainwindow():
mainwindow = tk.Tk()
mainwindow.geometry('350x350')
tk.Label(mainwindow, text="enter parameters below").grid(row=1)
getN = IntVar()
geti0 = IntVar()
getr0 = IntVar()
getbeta = StringVar(mainwindow, value='0')
getgamma = StringVar(mainwindow, value='0')
tk.Label(mainwindow, text="N").grid(row=2)
tk.Label(mainwindow, text="i0").grid(row=3)
tk.Label(mainwindow, text="r0").grid(row=4)
tk.Label(mainwindow, text="beta").grid(row=5)
tk.Label(mainwindow, text="gamma").grid(row=6)
e1 = tk.Entry(mainwindow,textvariable = getN)
e1.grid(row=2, column=1)
e2 = tk.Entry(mainwindow,textvariable = geti0)
e2.grid(row=3, column=1)
e3 = tk.Entry(mainwindow,textvariable = getr0)
e3.grid(row=4, column=1)
e4 = tk.Entry(mainwindow,textvariable = getbeta)
e4.grid(row=5, column=1)
e5 = tk.Entry(mainwindow,textvariable = getgamma)
e5.grid(row=6, column=1)
reg_int = mainwindow.register(lambda input, typez="int": callback(input, typez=typez))
reg_str = mainwindow.register(lambda input, typez="str": callback(input, typez=typez))
e1.config(validate ="key", validatecommand =(reg_int, '%P'))
e2.config(validate ="key", validatecommand =(reg_int, '%P'))
e3.config(validate ="key", validatecommand =(reg_int, '%P'))
e4.config(validate ="key", validatecommand =(reg_str, '%P'))
e5.config(validate ="key", validatecommand =(reg_str, '%P'))
solve = tk.Button(mainwindow, text='solve!', command=lambda: [values()]).grid(row=7, column=1, sticky=tk.W, pady=4)
def values():
readN = getN.get()
readi0 = geti0.get()
readr0 = getr0.get()
readbeta = eval(getbeta.get(),{"builtins": {}})
readgamma = eval(getgamma.get(), {"builtins": {}})
intN = int(readN)
inti0 = int(readi0)
intr0 = int(readr0)
intbeta = float(readbeta)
intgamma = float(readgamma)
print(intN,'\n',inti0,'\n',intr0,'\n',intbeta,'\n',intgamma)
mainwindow.mainloop()
mainwindow()
CodePudding user response:
Hi thanks to the mysterious poster that deleted a very well explained answer (Bryan Oakley) I was able to provide another way to solve my problem . Here is the code:
import tkinter as tk
from tkinter import IntVar,StringVar
###############################################################################
def callback(input,typez=None):
if typez == "int":
if input.isdigit():
# print(input)
return True
elif input == "":
# print(input)
return True
else:
print(input)
return False
if typez == "str":
if len(input) >=1 and input[0] == '/':
return False
if all([s.isdigit() or s =='/' for s in input]) and input.count('/') <= 1:
# print([s.isdigit() or s =='/' for s in input])
# print(input)
return True
elif all([s.isdigit() or s =='.' for s in input]) and input.count('.') <= 1:
# print([s.isdigit() or s =='.' for s in input])
# print(input)
return True
else:
print('no valid input : ',input)
return False
def mainwindow():
mainwindow = tk.Tk()
mainwindow.geometry('350x350')
tk.Label(mainwindow, text="enter parameters below").grid(row=1)
getN = IntVar()
geti0 = IntVar()
getr0 = IntVar()
getbeta = StringVar(mainwindow, value='0')
getgamma = StringVar(mainwindow, value='0')
tk.Label(mainwindow, text="N").grid(row=2)
tk.Label(mainwindow, text="i0").grid(row=3)
tk.Label(mainwindow, text="r0").grid(row=4)
tk.Label(mainwindow, text="beta").grid(row=5)
tk.Label(mainwindow, text="gamma").grid(row=6)
e1 = tk.Entry(mainwindow,textvariable = getN)
e1.grid(row=2, column=1)
e2 = tk.Entry(mainwindow,textvariable = geti0)
e2.grid(row=3, column=1)
e3 = tk.Entry(mainwindow,textvariable = getr0)
e3.grid(row=4, column=1)
e4 = tk.Entry(mainwindow,textvariable = getbeta)
e4.grid(row=5, column=1)
e5 = tk.Entry(mainwindow,textvariable = getgamma)
e5.grid(row=6, column=1)
reg_int = mainwindow.register(callback)
reg_str = mainwindow.register(callback)
e1.config(validate ="key", validatecommand =(reg_int, '%P', 'int'))
e2.config(validate ="key", validatecommand =(reg_int, '%P', 'int'))
e3.config(validate ="key", validatecommand =(reg_int, '%P', 'int'))
e4.config(validate ="key", validatecommand =(reg_str, '%P', 'str'))
e5.config(validate ="key", validatecommand =(reg_str, '%P', 'str'))
solve = tk.Button(mainwindow, text='solve!', command=lambda: [values()]).grid(row=7, column=1, sticky=tk.W, pady=4)
def values():
readN = getN.get()
readi0 = geti0.get()
readr0 = getr0.get()
readbeta = eval(getbeta.get(),{"builtins": {}})
readgamma = eval(getgamma.get(), {"builtins": {}})
intN = int(readN)
inti0 = int(readi0)
intr0 = int(readr0)
intbeta = float(readbeta)
intgamma = float(readgamma)
print(intN,'\n',inti0,'\n',intr0,'\n',intbeta,'\n',intgamma)
mainwindow.mainloop()
mainwindow()
It doesnt use lambda, but just passes the arg as in https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/entry-validation.html :
To set up this callback, you would use these two options in the Entry constructor:
self.w = Entry(self, validate='all',validatecommand=(okayCommand, '%d', '%i', '%S'), ... here my extra args ...)
Like:
e1.config(validate ="key", validatecommand =(reg_int, '%P', 'int'))
e2.config(validate ="key", validatecommand =(reg_int, '%P', 'int'))
e3.config(validate ="key", validatecommand =(reg_int, '%P', 'int'))
e4.config(validate ="key", validatecommand =(reg_str, '%P', 'str'))
e5.config(validate ="key", validatecommand =(reg_str, '%P', 'str'))
