【问题标题】:Python Tkinter, lambdas and callbacksPython Tkinter、lambdas 和回调
【发布时间】:2012-04-26 05:56:14
【问题描述】:

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() 之间的空间中,但随后我得到了缺少图像的错误。如何修改我的代码以适应它?

【问题讨论】:

    标签: python lambda callback scope tkinter


    【解决方案1】:

    您可以将默认值 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
    

    如果您将默认值设置为 image 而不是 img,那么您定义 func 的想法也会起作用:

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

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

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

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

    【讨论】:

    • 嗯,谢谢,效果很好,比我想做的要少得多!我不太明白它的作用......它是否从列表中获取图像并在 lambdas 范围内为其分配名称“图像”?那么它在调用 popImage 函数时会将新创建的图像值提供给它吗?再次感谢!
    • re:edit 感谢您让这一点更加清晰。 lambda e, NEW=image: self.popImage(NEW)) 是正在发生的事情。谢谢。
    • 是的,完全正确。使用不同的变量名确实可以说明发生了什么。
    猜你喜欢
    • 2012-08-07
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 2014-08-09
    • 2016-03-03
    • 1970-01-01
    • 2013-04-05
    相关资源
    最近更新 更多