在Tkinter的小NumPad

时间:2013-04-29 16:53:56

标签: python variables numbers tkinter

我正在尝试使用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。我找不到我做过的错误,我认为它可能与垃圾收集有关,但我不确定。

有人能帮帮我吗?真的很棒!

谢谢!

3 个答案:

答案 0 :(得分:2)

当lambda本身被声明时,你的lambda

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也是对的:我认为有两个独立的错误。请注意,我实际上没有测试过这个。