【问题标题】:Python & Tkinter - buttons command to set label textvariable issuePython & Tkinter - 设置标签文本变量问题的按钮命令
【发布时间】:2015-11-15 11:49:19
【问题描述】:

我正在玩 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()

【问题讨论】:

    标签: python button lambda tkinter


    【解决方案1】:

    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)
    

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

    【讨论】:

      【解决方案2】:

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

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

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

      还请注意,如果您执行bi = Button(...).grid(...)bi 将被分配grid 函数的结果,即None。在这种情况下,您无论如何都不需要bi,所以没关系,但这是另一个常见问题,所以最好不要养成这种习惯。

      【讨论】:

      • @SDilmac 如果它也为 OP 运行,他/她就不会问这个问题,你不觉得吗?
      • @tobias_k 太好了!谢谢人 - 传奇! bi是我之前尝试过的东西的剩菜,打算把它拿出来:-P..
      • @daansteraan 您可以做的另一件事是绑定 "&lt;Button-1&gt;" 事件,调用设置标签文本的函数。被调用的这个函数需要为事件对象指定一个参数,并且通过这个指向事件对象的参数,您可以访问其上的小部件(以及它的属性,在您的情况下是按钮的文本)事件发生,然后相应地修改标签。如果我所说的一切对你来说很奇怪,请暂时忽略它,但你可能必须了解“事件和绑定”的概念
      猜你喜欢
      • 1970-01-01
      • 2013-10-28
      • 2020-11-18
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 2020-01-26
      • 1970-01-01
      相关资源
      最近更新 更多