tkinter:for循环中的tag_bind只传递最后一个标记作为lambda事件函数

时间:2018-04-22 21:12:48

标签: python tkinter tags bind

过去几个小时我一直在努力处理这部分代码,所以我决定询问stackoverflow。

首先,这是我的代码:

def place_checkers_init(self):  
    for i,player_piece in enumerate(self.player_pieces):
        tag = "p"+str(i)
        square = self.frame.grid_slaves(player_piece.row, player_piece.col)[0]
        piece = square.create_oval(10,10,90,90,fill=player_piece.color)
        square.itemconfig(piece, tags = tag)
        print(square.gettags(piece))
        square.tag_bind(tag, '<1>', lambda event: self.player_move(tag))

为了简要说明背景,self.player_pieces是CheckerPiece对象的列表,仅用于存储有关棋子的行,列,颜色等的信息。 Self.frame是一个Frame对象,包含存储为网格的36个Canvas对象。我在这个代码块上尝试做的是使用存储在CheckerPiece对象中的行和列信息在这些单独的画布(棋盘图块)上创建检查器块(椭圆形),并将这些块中的每一个绑定到Button并执行class method self.player_move。

所以这就是我的问题:即使我将每个检查器分配给他们自己的标签,由于某种原因,所有部件最终都会得到for循环中最后一个部分的标签。也就是说,当我尝试打印(在终端上)检查器块的行和列时,我使用self.player_move的定义点击(在我的gui中):

def player_move(self, tag):
    index = int(tag[1])
    print(self.player_pieces[index].row, self.player_pieces[index].col)

它只打印(4,5)无论我点击哪一块,这是列表self.player_pieces中的最后一个棋子。

我的猜测是我的tag_bind的最后一个参数(lambda函数)出了问题,但我不知道该怎么办。

我能得到一些帮助吗?谢谢!

1 个答案:

答案 0 :(得分:1)

您问题的最低限度可以写成:

for f in [lambda: print(n, end=' ') for n in range(5)]:
    f()

输出:

4 4 4 4 4 # why do the lambdas only print the last value of 'n' ?

现在替换为:

for f in [lambda n=n: print(n, end=' ') for n in range(5)]:
    f()

输出

0 1 2 3 4 # yeah!