将 args 传递给 Python3 中的 Tkinter 回调验证函数,这可能吗?
Passing args to Tkinter Callback validating function in Python3, Is it possible?
我是 Python3 的新手,第一次尝试 tkinter,我最近回答了 using https://www.geeksforgeeks.org/python-tkinter-validating-entry-widget/ 提示。
现在我正在思考 reg_str = mainwindow.register(callback_str)
和 e4.config(validate ="key", validatecommand =(reg_str, '%P'))
的工作原理。
我用谷歌搜索并尝试在 Whosebug 上搜索,但找不到答案,
下面是我的最小可重现示例:
import tkinter as tk
from tkinter import IntVar,StringVar
###############################################################################
def callback_int(input,typez=None):
# print(typez)
if input.isdigit():
# print(input)
return True
elif input == "":
# print(input)
return True
else:
print(input)
return False
def callback_str(input, typez=None):
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_int)
reg_str = mainwindow.register(callback_str)
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()
程序打开一个小部件:
要求输入。
前 3 个条目行由 callback_int
验证,仅允许 int 数字,而最后 2 个条目行使用 callback_str
允许浮点数(如 1.5 或 0.5)和分数(如 1/7 或 5/) 7.
我的问题(抱歉拖了这么久)是:
有没有办法像 callback(typez = str)
一样将函数参数传递给 callback
这样我就可以仅使用一个回调函数来缩短我的代码,该回调函数对我的 int 和 string 值有不同的作用?如果我使用 reg_int = mainwindow.register(callback_int(input,typez='popo'))
我得到
line ...
if input.isdigit():
AttributeError: 'function' object has no attribute 'isdigit'
我猜问题出在:
reg_int = mainwindow.register(callback_int(input,typez='popo')) #AttributeError: 'function' object has no attribute 'isdigit'
reg_str = mainwindow.register(callback_str('pipi'))
但找不到任何有用的东西,或者我的方法方向错误
这使用 lambda
语句将 "str"
或 "int"
传递给 callback()
中的 typez
参数,因此 callback()
知道 input
是什么类型。这是基于我上面第一条评论的完整代码:
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()
您好,感谢神秘的发帖者删除了一个解释得很好的答案 (Bryan Oakley),我能够提供另一种方法来解决我的问题。这是代码:
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()
它不使用 lambda,只是像 https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/entry-validation.html 那样传递 arg :
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 ...)
喜欢:
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'))
我是 Python3 的新手,第一次尝试 tkinter,我最近回答了
现在我正在思考 reg_str = mainwindow.register(callback_str)
和 e4.config(validate ="key", validatecommand =(reg_str, '%P'))
的工作原理。
我用谷歌搜索并尝试在 Whosebug 上搜索,但找不到答案,
下面是我的最小可重现示例:
import tkinter as tk
from tkinter import IntVar,StringVar
###############################################################################
def callback_int(input,typez=None):
# print(typez)
if input.isdigit():
# print(input)
return True
elif input == "":
# print(input)
return True
else:
print(input)
return False
def callback_str(input, typez=None):
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_int)
reg_str = mainwindow.register(callback_str)
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()
程序打开一个小部件:
要求输入。
前 3 个条目行由 callback_int
验证,仅允许 int 数字,而最后 2 个条目行使用 callback_str
允许浮点数(如 1.5 或 0.5)和分数(如 1/7 或 5/) 7.
我的问题(抱歉拖了这么久)是:
有没有办法像 callback(typez = str)
一样将函数参数传递给 callback
这样我就可以仅使用一个回调函数来缩短我的代码,该回调函数对我的 int 和 string 值有不同的作用?如果我使用 reg_int = mainwindow.register(callback_int(input,typez='popo'))
我得到
line ...
if input.isdigit():
AttributeError: 'function' object has no attribute 'isdigit'
我猜问题出在:
reg_int = mainwindow.register(callback_int(input,typez='popo')) #AttributeError: 'function' object has no attribute 'isdigit'
reg_str = mainwindow.register(callback_str('pipi'))
但找不到任何有用的东西,或者我的方法方向错误
这使用 lambda
语句将 "str"
或 "int"
传递给 callback()
中的 typez
参数,因此 callback()
知道 input
是什么类型。这是基于我上面第一条评论的完整代码:
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()
您好,感谢神秘的发帖者删除了一个解释得很好的答案 (Bryan Oakley),我能够提供另一种方法来解决我的问题。这是代码:
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()
它不使用 lambda,只是像 https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/entry-validation.html 那样传递 arg :
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 ...)
喜欢:
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'))