【问题标题】:Python Tk canvas item event binding: iterating bindings over multiple itemsPython Tk 画布项目事件绑定:在多个项目上迭代绑定
【发布时间】:2012-11-28 17:49:17
【问题描述】:

我正在尝试使用 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)
            )

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

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

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

【问题讨论】:

    标签: python event-handling tkinter tk python-2.x


    【解决方案1】:

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

    在没有默认值的情况下,当调用lambda 函数时,使用the LEGB rule 查找card 的值——在本地范围内查找,然后是扩展范围,然后是全局范围,然后是内置范围。由于它没有在本地范围内定义,它会在扩展范围内(包含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)
                )
    

    【讨论】:

    • 非常感谢!我找到了一种解决方法,但是使用您的解决方案将使我的代码更容易编写并减少函数数量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-02
    • 2014-11-28
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    相关资源
    最近更新 更多