我正在尝试使用tkinter构建一个小数字垫,以便能够在纯触摸系统上输入密码。这就是我到目前为止所做的:
导入tkinter 来自tkinter import ttk
def main():
root = tkinter.Tk()
numpad = NumPad(root)
root.mainloop()
btn_list = [
'7', '8', '9',
'4', '5', '6',
'1', '2', '3', '0']
class NumPad(ttk.Frame):
def __init__(self, root):
ttk.Frame.__init__(self, root)
self.grid()
self.numpad_create()
def numpad_create(self):
r = 1
c = 0
for b in btn_list:
cmd= lambda: print(b)
self.b= ttk.Button(self, text=b,width=5,command=cmd).grid(row=r,column=c)
print(b)
c += 1
if c > 4:
c = 0
r += 1
main()
如果我启动程序,它会将数字b输出到shell,所以这样可行。按钮也显示为希望。但是如果我单击它们,我总是将0作为输出到shell。我找不到我做过的错误,我认为它可能与垃圾收集有关,但我不确定。
有人能帮帮我吗?真的很棒!
谢谢!
答案 0 :(得分:2)
cmd
没有捕获b
的值。 b
的最终状态为0
,这就是为什么所有按钮最终都会打印b
。
答案 1 :(得分:2)
你的lambda应该像这样指定:
cmd= lambda b=b: print(b)
这会将b
的当前值绑定为lambda中名为b
的参数的默认值。如果没有此绑定,lambda将在按下时使用b
的值,而不是创建时的值。
我个人觉得在两种情况下使用相同的变量都很困惑;我个人会这样写,它功能相同但更容易理解:
cmd= lambda button=b: print(button)
答案 2 :(得分:0)
NumPad.numpad_create
中的for循环遍历每个按钮编号并将其存储在self.b
中。问题是每个数字都会覆盖self.b
的先前值,因此实际存储的唯一值是0
。 tkinter自动垃圾收集没有实时引用的对象。将另一个属性添加到NumPad
这是一个列表,并将所有按钮对象放入其中。
@thkang也是对的:我认为有两个独立的错误。请注意,我实际上没有测试过这个。