1

我正在尝试使用 tkinter 构建一个小数字键盘,以便能够在纯触摸系统上输入密码。这是我到目前为止所拥有的:

从 tkinter 导入 tkinter 导入 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 打印到外壳上,所以这是可行的。按钮也按需要显示。但是如果我点击它们,我总是得到 0 作为 shell 的输出。我找不到我犯的错误,我认为这可能与垃圾收集有关,但我不确定。

有人可以帮我吗?真的很棒!

谢谢!

4

3 回答 3

4

你的 lambda 应该这样指定:

cmd= lambda b=b: print(b)

这会将 的当前值绑定为lambda 中b命名的参数的默认值。b如果没有此绑定,lambda 将使用b按下时的值,而不是创建时的值。

就我个人而言,我发现在两种情况下使用相同的变量会令人困惑。我个人会这样写,功能相同但更容易理解:

cmd= lambda button=b: print(button)
于 2013-04-29T17:53:27.750 回答
2

cmd,您的 lambda,没有捕获blambda 本身声明时的值。bis的最终状态0,这就是为什么你的所有按钮最终都打印出来的原因b

于 2013-04-29T17:07:10.193 回答
0

for 循环NumPad.numpad_create遍历每个按钮编号并将它们存储在self.b. 问题是每个数字都会覆盖 的先前值self.b,因此实际存储的唯一值是0。tkinter 自动垃圾收集没有实时引用的对象。添加另一个属性NumPad是列表并将所有按钮对象放入其中。

@thkang 也是对的:我认为有两个单独的错误。请注意,我还没有实际测试过这个。

于 2013-04-29T17:12:20.047 回答