Python& Tkinter - buttons命令用于设置标签文本变量问题

时间:2015-08-21 13:44:01

标签: python button lambda tkinter

我正在玩Tkinter并从基础构建计算器。尽可能地尝试和理解尽可能多地了解事件和图书馆。

现在我处于这样的程度,我只想让按钮将按钮上的值传递到顶部的标签。

我使用for循环来创建大多数按钮以避免冗余代码,但现在传递到标签中textvariable的唯一值是最后一项,'。',在我的按钮列表中,我不知道为什么会这样。有人可以帮忙吗?

代码如下:

from Tkinter import * import Tkinter as tk # main window root = Tk() root.title('Calculator') # button set buttons = ['1','2','3','4','5','6','7','8','9','0','+','-','/','*','.'] sum_value = StringVar() # output window output_window = tk.Label(root, textvariable=sum_value, width=20, height=2).grid(row=0, columnspan=3, sticky=(E,W)) # button creation r=1 c=0 for i in buttons: if c < 2: bi = tk.Button(root, text = i, command = lambda: sum_value.set(i), padx = 5, pady = 3).grid(row = r, column = c, sticky = (N,S,E,W)) c += 1 else: bi = tk.Button(root, text = i, command = lambda: sum_value.set(i), pady = 3).grid(row = r,column = c,sticky = (N,S,E,W)) r += 1 c = 0 # clear and equals button clear = tk.Button(root,text='=',padx = 5, pady=3).grid(row=6,column=0,sticky=(N,S,E,W)) clear = tk.Button(root,text='CLEAR',padx = 5, pady=3).grid(row=6,column=1, columnspan = 2,sticky=(N,S,E,W)) root.mainloop()

2 个答案:

答案 0 :(得分:1)

这是在循环中声明lambda的常见缺陷。变量ilambda 被称为时评估,而不是在定义时评估,因此所有函数最终都使用的值是在循环的最后一次迭代中分配给i。有一些方法可以解决这个问题,例如:使用参数并为其分配一个默认值,该值将在定义函数时进行评估。

在您的情况下,您可以将lambdas更改为此表单,然后它应该有效:

bi = tk.Button(..., command=lambda i=i: sum_value.set(i), ...)
bi.grid(...)

另请注意,如果您执行bi = Button(...).grid(...)bi将被分配grid功能的结果,即None。在这种情况下你不需要bi,所以它并不重要,但这是另一个常见问题,所以最好不要养成这种习惯。

答案 1 :(得分:0)

This问题为您的困境提供了一个很好的解释。

有两种解决方法:

(1)如上所述的默认参数方法。

(2)每次创建lambda时都创建一个新范围:

for i in buttons:
    if c < 2:
        bi = tk.Button(root, text = i, command = (lambda a: lambda : sum_value.set(a))(i), padx = 5, pady = 3).grid(row = r, column = c, sticky = (N,S,E,W))        
        c += 1
    else:
        bi = tk.Button(root, text = i, command = (lambda a: lambda : sum_value.set(a))(i), pady = 3).grid(row = r,column = c,sticky = (N,S,E,W))
        r  += 1
        c = 0

让我们看看它的作用:

(lambda a: lambda : sum_value.set(a))(i)

使用参数i调用外部lambda函数,该函数为内部lambda函数创建闭包。闭包是一个对象,它记住封闭范围中的值。 内部lambda函数可以访问i在声明lambda函数时所具有的值。