【问题标题】:Generate Tkinter Buttons dynamically动态生成 Tkinter 按钮
【发布时间】:2011-05-13 06:42:16
【问题描述】:

我想生成 n 数量的 Tkinter Buttons 来做不同的事情。我有这个代码:

import Tkinter as tk

for i in range(boardWidth):
    newButton = tk.Button(root, text=str(i+1),
                    command=lambda: Board.playColumn(i+1, Board.getCurrentPlayer()))
    Board.boardButtons.append(newButton)

如果boardWidth 是5,虽然我得到标记为15 的按钮,但当点击它们时,它们都会变成Board.playColumn(5, Board.getCurrentPlayer())

我需要第一个按钮执行Board.playColumn(1, Board.getCurrentPlayer()),第二个按钮执行Board.playColumn(2, Board.getCurrentPlayer()),依此类推。

【问题讨论】:

    标签: python user-interface button tkinter


    【解决方案1】:

    您的问题是您在同一个命名空间中创建了许多 lambda 对象,而这些 lambdas 引用了外部范围内的名称。这意味着它们不会成为闭包,并且它们不会存储对对象的引用,直到以后......当它发生时,所有 lambdas 将引用 i 的最后一个值。

    尝试使用回调工厂来解决这个问题:

    import Tkinter as tk
    
    def callbackFactory(b, n):
        def _callback():
            return b.playColumn(n, b.getCurrentPlayer())
        return _callback
    
    for i in range(boardWidth):
        newButton = tk.Button(root, text=str(i+1), 
            command=callbackFactory(Board, i+1))
        Board.boardButtons.append(newButton)
    

    另一个想法是将 i 的当前值作为默认参数值存储在 lambda 对象中,而不是依赖闭包行为来存储引用:

    for i in range(boardWidth):
        newButton = tk.Button(root, text=str(i+1), 
            command=lambda x=i: Board.playColumn(x+1, Board.getCurrentPlayer()))
        Board.boardButtons.append(newButton)
    

    【讨论】:

    • 按照 martineau 的建议尝试了第二个示例。感谢您解释为什么会发生这种情况!
    【解决方案2】:

    我认为问题在于lambdafor 循环结束后获取i 的最终值。这应该可以解决这个问题(未经测试):

    import Tkinter as tk
    
    for i in range(boardWidth):
        newButton = tk.Button(root, text=str(i+1),
                        command=lambda j=i+1: Board.playColumn(j, Board.getCurrentPlayer()))
        Board.boardButtons.append(newButton)
    

    更新

    顺便说一句,这是通过向lambda 函数添加一个参数来实现的,其默认值是根据在循环中创建每个参数时i 的值计算得出的,而不是引用@987654327 的最终值@ 在其中的表达式稍后执行时通过闭包。

    【讨论】:

      猜你喜欢
      • 2013-01-02
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多