将许多按钮绑定到一个函数,并将每个按钮的名称作为参数传递

时间:2019-01-05 12:48:48

标签: python tkinter

请注意,我的问题与此相反:Creating functions in a loop因为我有很多按钮和一个功能,而没有很多功能。

我从for循环中创建10个带编号的按钮,然后尝试将每个按钮绑定到一个将打印按钮编号的函数;参见下面的代码:

import tkinter as tk

class Window(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        # creating buttons and adding them to dictionary

        self.buttons = {}
        for number in range(1, 11):
            self.buttons.update({'button' + str(number): tk.Button(self, height=1, width=4, bg="grey", text=number)})

        # example of a pair in the dictionary: 'button2': <Tkinter.Button instance at 0x101f9ce18>


        """ bind all the buttons to callback, each button is
            named something like 'button3',so I take the number off
            the end of its name and feed that as an argument to Callback"""

        for button in self.buttons:
            self.buttons[button].bind('<Button-1>', lambda event: self.Callback(event, button[6:]))
            self.buttons[button].pack(side='left')

    def Callback(self, event, num):
        print(num)

所有按钮出现在窗口上都没问题,但是当我单击其中的任何一个时,控制台都会打印“ 10”,而不是按钮的编号。看来该功能只是记住它给出的最后一个参数。

1 个答案:

答案 0 :(得分:3)

首先让我们更正您的代码以提供所需的答案。

import tkinter as tk

class Window(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        self.buttons = {}
        for number in range(1, 11):
            self.buttons.update({'button' + str(number): tk.Button(self, height=1, width=4, bg="grey", text=number)})

        for button in self.buttons:
            self.buttons[button].bind('<Button-1>', lambda event, num=button[6:]: self.Callback(event, num))
            self.buttons[button].pack(side='left')               #\____________/

    def Callback(self, event, num):
        print(num)

Window().mainloop()

说明

诀窍在于lambda函数的工作方式。

在编写lambda event: self.Callback(event, button[6:])时,该实例没有得到 button[6:] 的值并将其存储。相反,它会创建一个 closure ,这有点像对自身的注释:“ 我应该在我当时寻找变量button(迭代器)的值是什么称为”。

现在,当循环结束并且每个小部件都已准备好并进行设置时,您调用它,它将在那个时候寻找 button 的值,这当然是迭代(此处为button10)。

num=button[6:]使函数在定义lambda时存储计数器的当前值(此处为 button ),而不是等待查找的值按钮

积分:BrenBarn


只需添加,您就可以使用command小部件的Button属性以更少的代码来完成当前的工作。这是一个例子。

import tkinter as tk

class Window(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        for number in range(1, 11):
            tk.Button(self, height=1, width=4, bg="grey", text=number, command=lambda num=number: self.Callback(num)).pack(side='left')

    def Callback(self, num):
        print(num)

Window().mainloop()