2

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

4

1 回答 1

2

问题是 lambda 表达式lambda event: self.OnClicked(event,by[i]))。您可以在此处阅读有关基本问题的更多信息:(lambda) 函数闭包捕获什么?.

但简而言之: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)
于 2012-08-18T14:04:37.583 回答