Python Tk画布项事件绑定:在多个项上迭代绑定



我正在尝试使用Python对象作为Tk画布项的包装器。例如:

class PlayingCard:
def __init__(self, item):
self.item = item
aceOfSpades = PlayingCard(canvas.create_image((coordinates), image = PhotoImage(aceofspades.gif)))
print aceOfSpades.item
>>> <canvas item id>

这样,如果我需要操作画布项目,我可以通过一个对象引用它:

aceOfSpades.item.move(dx, dy)

所以,问题是我有很多对象(事实上是52个),每个对象都有自己的self.item,它引用了一个画布图像项,如果对象满足某些条件,我想迭代这些对象,并为它们的画布项创建事件绑定。这是我的解决方案(伪pycode):

def event_handler(card):
card.attribute = updated_value
for card in [list of card objects]:
if card.attribute == test_condition:
canvas.tag_bind(
card.item, #this is the item id stored in the PlayingCard.item variable
<Event Sequence>,
lambda x: event_handler(card)
)

问题是,迭代完成后,所有事件绑定都会将相同的参数传递给事件处理程序。

换句话说,我想将card对象作为参数传递给事件处理程序,这样,当与该卡的object.item画布项对应的事件发生时,事件处理程序就可以访问该卡对象。然而,该代码所做的是将相同的参数(即card对象)传递给事件处理程序,而不考虑画布项。在代码中,这意味着如果事件序列是单击,那么单击任何卡片画布项都会调用函数event_handler(<last card object in iteration>),而我希望单击画布项来调用event_handler(<corresponding card object>)

我说得通吗?我不明白为什么这种方法不能产生我想要的结果。

lambda函数中使用具有默认值的可选关键字参数。默认值在定义lambda时绑定到lambda,因此在lambda中,card是一个局部变量,每个lambda将具有不同的card默认值。

在没有默认值的情况下,当调用lambda函数时,会使用LEGB规则查找card的值——在Local、Extended、Global和Builtin范围中查找。由于它没有在本地作用域中定义,所以它在扩展作用域(包含for card in [list of cards]的作用域)中找到它。其中,card引用list of cards中的最后一张卡。这就是为什么所有单击事件都会影响相同的card

for card in [list of card objects]:
if card.attribute == test_condition:
canvas.tag_bind(
card.item, #this is the item id stored in the PlayingCard.item variable
<Event Sequence>,
lambda x, card = card: event_handler(card)
)

相关内容

  • 没有找到相关文章

最新更新