简体   繁体   English

如何为循环中创建的多个按钮使用与命令相同的功能?

[英]How do you use the same function as the command for multiple buttons created in a loop?

I am creating a tic-tac-toe board of buttons. 我正在创建一个井字游戏板按钮。 Each button, when clicked, should switch to an X or an O on an alternating basis. 单击每个按钮时,应交替切换为X或O。 I have created the buttons inside for loops, and would, if possible, like to avoid initializing them each separately. 我已经在for循环中创建了按钮,并且在可能的情况下希望避免分别单独初始化它们。 I have tried passing the button to the function by using lambda, and I have tried eliminating the problem of parameters in commands by calling the buttons self.bttn (as this is all taking place within my modified Frame class). 我尝试使用lambda将按钮传递给函数,并且尝试通过调用按钮self.bttn消除命令中的参数问题(因为这全部发生在修改后的Frame类中)。 However, in both cases, I come across the problem that, regardless of which of the 9 buttons I click on, the final button created by the for loops responds. 但是,在这两种情况下,我都遇到了一个问题,即无论我单击9个按钮中的哪个按钮,for循环创建的最终按钮都会响应。

def __build_board(self):
    """ Creates tic-tac-toe board of 9 blank buttons. """
    for row_num in range(3):
        for col_num in range(3):
            self.bttn = Button(self, text = "    ", command = self.__change_button)
            self.bttn.grid(row = row_num + 1, column = col_num, sticky = W)

That's the way that I tried it with self.bttn. 这就是我用self.bttn尝试的方式。 self.__change_button merely switches the text within self.bttn to an X or O. And this is the way I tried it with lambda... self .__ change_button只是将self.bttn中的文本切换为X或O。这就是我使用lambda尝试的方式...

def __build_board(self):
    """ Creates tic-tac-toe board of 9 blank buttons. """
    for row_num in range(3):
        for col_num in range(3):
            bttn = Button(self, text = "    ", command = lambda: self.__change_button(bttn))
            bttn.grid(row = row_num + 1, column = col_num, sticky = W)

I think I understand why these ways of going about it do not work. 我想我理解为什么这些解决方法不起作用。 Seemingly, I have commanded all the buttons to change the text of the final button, but I'm at a loss as to how I should get them to each change their own text the way I want. 看来,我已命令所有按钮更改最终按钮的文本,但是我对如何让它们按自己想要的方式更改自己的文本感到困惑。 Any help would be greatly appreciated. 任何帮助将不胜感激。

This is a tricky problem... 这是一个棘手的问题...

the reason is that the lambda will be tied to the bttn variable , not to its value and therefore all the buttons will act on the last button (because that will be the value of the variable after the loop). 原因是lambda将绑定到bttn 变量 ,而不是其值,因此所有按钮将作用于最后一个按钮(因为这将是循环后变量的值)。

To see this consider: 看到这个考虑:

x = 1
y = lambda : x
print(y()) # will print 1
x = 2
print(y()) # will print 2; lambda captures variables, not values

A possible work-around is: 可能的解决方法是:

def __build_board(self):
    """ Creates tic-tac-toe board of 9 blank buttons. """
    for row_num in range(3):
        for col_num in range(3):
            def mkbutton():
                b = Button(self, text = "    ",
                           command = lambda: self.__change_button(b))
                return b
            bttn = mkbutton()
            bttn.grid(row = row_num + 1, column = col_num, sticky = W)

this way each lambda will be tied to its own separate variable b . 这样,每个lambda都将绑定到其自己的单独变量b

Normally this kind of issue can be solved more easily with the frequent pattern: 通常,使用频繁模式可以更轻松地解决此类问题:

x = lambda y=y: ...

where the value y is copied as default for an optional parameter of the lambda. 默认情况下,将值y复制为lambda的可选参数。

In your case however this approach is not possible because at the time the lambda is evaluated the Button instance doesn't exist yet (so you cannot store it as a default parameter value in the lambda itself). 但是,在您的情况下,这种方法是不可能的,因为在评估lambdaButton实例尚不存在(因此,您无法将其作为默认参数值存储在lambda本身中)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何更新循环中创建的按钮和标签的 Tkinter 参数? - How do you update Tkinter parameters for buttons and labels created in a loop? 你如何为函数使用循环? - How do you use a loop for a function? 如何使用for循环为按钮提供功能? - How do I use a for loop to give my buttons a function? 如何使用在 Python 中的另一个 function 中创建的列表? - How do you use a list that was created in another function in Python? 如何合并通过 for 循环创建的数据框(同名)? - How do you merge data frames (with the same name) created through a for loop? 如何使用for循环创建按钮,然后可以分别在命令功能中分别对其进行配置? - How to use for loop to create buttons that can be then each configured separately in my command function? 您如何动态地为按钮列表分配相同的功能但不同的参数? - How do you dynamically assign a list of buttons the same function but different arguments? 使用 tkinter 设置由 for 循环创建的多个按钮的行 - Setting row of multiple buttons created by for loop with tkinter 如何指定 setuptools 创建的命令脚本的 shebang 行 - How do you specify the shebang line of a command script created by setuptools 你如何在命令(discord.py)中创建一个 function 只允许你在一分钟内使用一次命令? - How do you create a function in a command(discord.py) that only lets you use a command once in one minute?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM