我正在尝试使用多个按钮自动填充屏幕(使用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个按钮,我想自动完成。我该如何设置插槽?
答案 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)