【问题标题】:Python Tkinter button callbackPython Tkinter 按钮回调
【发布时间】:2013-04-11 01:38:06
【问题描述】:

当我单击由 for 循环创建的每个按钮时,我试图打印出按钮编号。以下是我尝试过的。

import Tkinter as tk
root=tk.Tk()

def myfunction(a):
        print a

for i in range(10):
    tk.Button(root,text='button'+str(i),command=lambda:myfunction(i)).place(x=10,y=(10+(25*i)))
root.mainloop()

但不是打印出每个按钮编号,而是每次都给我最后一个按钮编号。有什么我可以做的,这样当我单击按钮 1 时,它会为 2 打印 1,2 ,依此类推?

【问题讨论】:

  • jared 的代码有点 hack,但这是由 lambda 函数引起的,如果你使用类,你不会有这个问题,command=self.command 并且属性对于类的对象是唯一的.

标签: python button callback tkinter


【解决方案1】:

简单的解决方法是在每次创建 lambda 函数时使用 i 的当前值初始化 lambda 函数。这可以使用另一个虚拟变量 j 的 Python 默认值来完成。

command = lambda j=i: myfunction(j)

【讨论】:

    【解决方案2】:

    Blender 的答案是一个聪明的解决方案,但如果您被函数抽象所迷惑,这是另一种可能的方法。它实际上只是创建了一个映射,保存在 buttons 中,从 Button 小部件到它们的正确编号。

    import Tkinter as tk
    root = tk.Tk()
    
    def myfunction(event):
        print buttons[event.widget]
    
    buttons = {}
    for i in range(10):
        b = tk.Button(root, text='button' + str(i))
        buttons[b] = i # save button, index as key-value pair
        b.bind("<Button-1>", myfunction)
        b.place(x=10,y=(10+(25*i)))
    root.mainloop()
    

    【讨论】:

      【解决方案3】:

      这是因为您的匿名函数中的i 指的是计数器变量,而不是值:

      from __future__ import print_function
      
      x = [lambda: print(i) for i in range(10)]
      
      for f in x:
          f()
      

      这会产生 10 个连续的9s 的输出。

      要解决这个问题,您必须使用两个 lambdas 和阴影 i 和一个 second 函数(它会创建您的第一个函数):

      from __future__ import print_function
      
      x = [(lambda i: (lambda: print(i)))(i) for i in range(10)]
      
      for f in x:
          f()
      

      虽然此时,您最好只创建一个命名函数:

      def my_command(i):
          def inner_function():
              return my_function(i)
      
          return inner_function
      

      并像这样使用它:

      tk.Button(root, text='button' + str(i), command=my_command(i))
      

      【讨论】:

        【解决方案4】:

        问题在于 tk 中的 Button 命令会忽略任何参数,因此在 mycommand(data) 之类的数据中会忽略数据。

        我经常使用按钮,并决定将 tk 按钮子类化以包含数据。我称它为 DataButton 并添加了一个数据成员(在本例中为索引号)。这样,当单击它时,它会传回其数据。 (索引号)现在,只要我希望它保存诸如索引甚至消息之类的信息,我都会使用 DataButton。

        【讨论】:

        • 它会帮助python初学者(像我一样)看到你的新类的实现代码。
        猜你喜欢
        • 2013-04-05
        • 2013-12-18
        • 2013-04-13
        • 1970-01-01
        • 1970-01-01
        • 2014-01-10
        • 1970-01-01
        • 1970-01-01
        • 2021-08-27
        相关资源
        最近更新 更多