Python Tkinter,lambdas和回调

时间:2012-04-13 20:48:09

标签: python lambda callback scope tkinter

Windows 7x64 Python2.7

我希望将Lexical closures in Python线程解决方案应用于我的代码。附加读物Closures in a for loop and lexical environment

我浏览图像列表,缩略图对并显示缩略图,点击标签后,它应显示一个新的TopLevel,其中包含完整大小的图像。

实际发生的是它只显示了ImagePairs的最后一个图像。搜索一下,我发现上面发布的帖子,但我不确定如何将它应用到我的情况中。

            row, col = 0, 0
            #create a frame for the row
            rowFrame = Frame(master)
            for image, thumb in ImagePairs:
                curLbl = Label(rowFrame, image=thumb)
                curLbl.grid(row=0, column=col, sticky='news')

                curLbl.bind('<Button-1>', lambda e:self.popImage(image))  #or curLbl.image

                col += 1
                if col >= 3:
                    rowFrame.grid(row=row)
                    #create a new frame, for the next row
                    rowFrame = Frame(master)
                    col = 0
                    row += 1

我想要制作一个类似

的功能
def func(img=img):
   return img

并将其插入grid()和bind()之间的空格中,但是我得到了丢失图像的错误。如何修改我的代码以适应它?

1 个答案:

答案 0 :(得分:4)

您可以将默认值image = image添加到lambda本身:

for image, thumb in ImagePairs:
            curLbl = Label(rowFrame, image=thumb)
            curLbl.grid(row=0, column=col, sticky='news')
            curLbl.bind('<Button-1>', lambda e, image = image:self.popImage(image))  #or curLbl.image

如果您使用默认值func代替image,那么定义img的想法也会有效:

def func(e, img = image):
    self.popImage(img)

要记住的关键是在lambda(或函数)定义时绑定默认值。

因此,每次循环时,都会使用自己的局部变量image定义一个新的lambda,并在定义时限绑定image的默认值。因此,当稍后调用lambda时,访问右image

对比没有提供默认值的情况:image不再是lambda的局部变量。当调用lambda时,Python会在封闭范围内寻找它。但到那时完成for循环并且封闭范围中的image被设置为ImagePairs中的最后一个值。 这就是为什么无论你按下什么按钮你都得到相同的最后一张图像:所有lambda都访问了同一个变量image的值。