2015-08-21 27 views
1

我正在玩Tkinter并从底部构建一个计算器。尽可能地尝试和理解尽可能多的关于事件和图书馆的知识,尽我所能。Python&Tkinter - 按钮命令来设置标签文本变量问题

现在我正处在一个点,我只想让按钮将按钮上的值传递给顶部的标签。

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

代码:

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()

回答

1

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

在你的情况,你可以改变你lambdas这种形式,那么它应该工作:

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

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

+0

他的代码已经在运行 – dsgdfg

+0

@SDilmac如果它也在运行OP,他/她不会问这个问题,你不觉得吗? – nbro

+0

@tobias_k太好了!感谢人 - 传奇! bi是我之前尝试过的东西的剩菜,意思是把它拿出来:-P .. – daansteraan

0

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

有解决此两种方法:如上所述

(1)默认参数方法。

(2)创建的每个拉姆达时间新范围的创作:

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) 

外lambda函数被调用,参数i,这为内部lambda函数创建了一个闭包。闭包是一个记住封闭范围中的值的对象。 内部lambda函数将有权访问在声明lambda函数时i所具有的值。