绑定wxpython中的事件仅适用于最后一个

时间:2012-08-18 13:50:05

标签: python wxpython signals-slots

我正在尝试使用多个按钮自动填充屏幕(使用for循环)

以下是摘录:

    i = 0
    for w in [1,2,3,4,5,6,7,8]:
        by.append(wx.Button(panel,label=w,pos = wx.Point(50*i,0)))
        by[i].Bind(wx.EVT_LEFT_DOWN,lambda event: self.OnClicked(event,by[i]))
        i += 1
    i = 0

当事件发生时,由于我设置了i = 0,所有事件都被路由到第一个按钮,即使我点击最后一个按钮。我知道,如果我设置插槽没有for循环它会工作。但是我要说我需要在屏幕上创建大约50个按钮,我想自动完成。我该如何设置插槽?

1 个答案:

答案 0 :(得分:2)

问题是lambda表达式lambda event: self.OnClicked(event,by[i]))。您可以在此处详细了解基本问题:What do (lambda) function closures capture?

但简而言之:i在创建lambda表达式时并不固定。循环结束后,所有lambda表达式仍然引用i。这意味着它们都具有相同的价值。

一个肮脏的修复方法是使用它:

by[i].Bind(wx.EVT_LEFT_DOWN,lambda event, i=i: self.OnClicked(event,by[i]))

但是使用另一个辅助函数来进行变量绑定可能会更好:

def addOnClicked(i,w):
    by.append(wx.Button(panel,label=w,pos = wx.Point(50*i,0)))
    by[i].Bind(wx.EVT_LEFT_DOWN,lambda event: self.OnClicked(event,by[i]))

for i in range(8):
    addOnClicked(i,i+1)