Tkinter CheckBox组件command参数执行失败:缺少1个必需的位置参数'self'
解决Tkinter复选框command参数调用函数的参数不匹配问题
这个错误提示看起来是缺self,但其实是个误导——真正的问题是函数参数不匹配。咱们一步步拆解:
问题根源
你的LthCheck和WthCheck函数定义时要求传入一个Msg参数,而:
- 输入框绑定
<FocusOut>事件时,Tkinter会自动传递一个event对象作为参数,刚好填满了Msg的位置,所以运行正常; - 下拉框的
command会把选中的选项字符串作为参数传递,也能匹配Msg; - 但复选框的
command在触发时不会传递任何参数,调用LthCheck和WthCheck时没有传入Msg,就会抛出“缺少位置参数”的错误(Python错误提示里的self是个乌龙,因为它把普通函数当成了类方法来判断)。
修复方案
咱们需要让检查函数和计算函数兼容“有无参数都能调用”的场景,有两种简单的方式:
方式1:给参数设置默认值
修改检查函数和计算函数,让参数可选:
# 计算变量 - 主函数,每次表单发生变化时运行 def CalcVariables(Msg=None): Msg = "Run Calculations" print(Msg) # 检查长度输入框内容是否合法 def LthCheck(Msg=None): try: float(Lth.get()) except: Msg = "Length box only numbers." if Msg is None else Msg print(Msg) Lth.focus() return # 检查宽度输入框内容是否合法 def WthCheck(Msg=None): try: int(Wth.get()) except ValueError: Msg = "Width box only accepts numbers." if Msg is None else Msg print(Msg) Wth.focus() return
方式2:用可变参数兼容所有情况
如果不需要使用传入的参数(比如你在函数里直接覆盖了Msg的值),可以直接用*args接受任意数量的参数,更简洁:
# 计算变量 - 主函数,每次表单发生变化时运行 def CalcVariables(*args): Msg = "Run Calculations" print(Msg) # 检查长度输入框内容是否合法 def LthCheck(*args): try: float(Lth.get()) except: Msg = "Length box only numbers." print(Msg) Lth.focus() return # 检查宽度输入框内容是否合法 def WthCheck(*args): try: int(Wth.get()) except ValueError: Msg = "Width box only accepts numbers." print(Msg) Wth.focus() return
修复后的完整代码
把上面的函数替换后,完整代码如下:
from tkinter import * from tkinter import ttk Form1=Tk() # 计算变量 - 主函数,每次表单发生变化时运行 def CalcVariables(*args): Msg = "Run Calculations" print(Msg) # 运行多个函数 - 绑定到组件的command参数实现功能 def MultipleFunctions(*funcs): def FuncLoop(*args, **kwargs): for f in funcs: f(*args, **kwargs) return FuncLoop # 检查长度输入框内容是否合法 def LthCheck(*args): # 检查输入是否为数字,若不是则给出警告并退出 try: float(Lth.get()) except: Msg = "Length box only numbers." print(Msg) Lth.focus() return # 检查宽度输入框内容是否合法 def WthCheck(*args): # 检查输入是否为数字,若不是则给出警告并退出 try: int(Wth.get()) except ValueError: Msg = "Width box only accepts numbers." print(Msg) Wth.focus() return # 长度输入框 Lth = Entry(Form1,width=10) Lth.grid(row=0, column=1, sticky=W) Lth.insert(0,10) Lth.bind("<FocusOut>",MultipleFunctions(LthCheck, CalcVariables)) Label (Form1, text="Length").grid(row=0, column=0, sticky=W) # 宽度输入框 Wth = Entry(Form1,width=10) Wth.grid(row=1, column=1, sticky=W) Wth.insert(0,1) Wth.bind("<FocusOut>",MultipleFunctions(WthCheck, CalcVariables)) Label (Form1, text="Width").grid(row=1, column=0, sticky=W) # 类型下拉框 Type = [ "Type 1", "Type 2", ] PartStyle = StringVar() PartStyle.set(Type[0]) PartStyleDrop = OptionMenu(Form1, PartStyle, *Type, command=MultipleFunctions(LthCheck, WthCheck, CalcVariables)) PartStyleDrop.grid(row=3, column=1,sticky=W) Label (Form1, text="Part").grid(row=3, column=0, sticky=W) # 复选框 MT = IntVar() ModType = Checkbutton(Form1, text = "Modify", variable = MT, onvalue = 1, offvalue =0, command= MultipleFunctions(LthCheck, WthCheck, CalcVariables)) ModType.grid(row=4,column=0) Lth.focus() Form1.mainloop()
现在点击复选框,就会正常调用检查函数和计算函数,不会再报错啦。
内容的提问来源于stack exchange,提问作者Douglas
相关产品推荐
相关产品推荐

