Tkinter在按钮按下时不更改图像

6

我已经将一张图片加载到tkinter标签中,并且该图片在标签中显示。当我按下按钮时,我需要更改该图片。当按钮被按下时,旧的图片消失了,但新的图片没有显示。

我的代码如下:

import Tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()

def change_pic(labelname):
 photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
 labelname.configure(image=photo1)
 print "updated"

vlabel=tk.Label(root)
photo = ImageTk.PhotoImage(Image.open('cardframe.jpg'))
vlabel.configure(image=photo)
vlabel.pack()
b2=tk.Button(root,text="Capture",command=lambda:change_pic(vlabel))
b2.pack()
root.mainloop()

我不知道PIL是否与Tkinter的PhotoImage相同。在Python中,有垃圾回收机制,有时它并不能按照我们的意愿工作。你需要将图像作为一个单独的实例获取,然后将其应用到类中,否则Python会收集你的图像实例。image = Image.open("demo.jpg")photo = PhotoImage(image)一起使用可能会起作用。 - Preston Hager
@PrestonHager 尝试过了,但不起作用。 - Emmanu
3个回答

8

def change_pic(labelname)函数中,你需要添加labelname.photo = photo1以确保photo1不被垃圾回收。

def change_pic(labelname):
    photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
    labelname.configure(image=photo1)
    labelname.photo = photo1
    print "updated"

P.S. 看起来labelname.photo = photo1labelname.image = photo1都可以使用。

请查看http://effbot.org/tkinterbook/label.htm了解更多细节。

您可以使用标签来显示PhotoImage和BitmapImage对象。 在此过程中,请确保保留对图像对象的引用, 以防止Python的内存分配器将其垃圾回收。 您可以使用全局变量或实例属性,或者更简单的是,只需向窗口小部件实例添加一个属性即可。


我想知道是否有这样一个已知的问题,为什么它没有在配置函数内完成? - unlut

4
以下是所做的编辑:
  1. 我重新组织了您的代码布局,并在可能的情况下简化了其语法。这些更改旨在使您的代码更易于阅读。
  2. 通常我们将PIL对象作为tk的子集/子代。只要它是根的一部分(即它是根或任何子窗口小部件的子项),您的PIL对象就可以工作。
以下是您的可用代码:
import Tkinter as tk
from PIL import Image, ImageTk

def change_pic():
    vlabel.configure(image=root.photo1)
    print "updated"

root = tk.Tk()

photo = 'cardframe.jpg'
photo1 = "demo.jpg"
root.photo = ImageTk.PhotoImage(Image.open(photo))
root.photo1 = ImageTk.PhotoImage(Image.open(photo1))

vlabel=tk.Label(root,image=root.photo)
vlabel.pack()

b2=tk.Button(root,text="Capture",command=change_pic)
b2.pack()

root.mainloop()

0

我加了一行代码,现在它可以工作了:

import tkinter as tk                        # I am using python 3 on windows so the tkinter is lowercased
from PIL import Image, ImageTk
root = tk.Tk()

def change_pic(labelname):
    global photo1                           # This is the only new line you need, I believe
    photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
    labelname.configure(image=photo1)
    print("updated")                        # Again I'm using python 3 on windows so syntax may differ.
    root.update()                           # You don't need this statement in this case, but it never hurts

vlabel=tk.Label(root)
photo = ImageTk.PhotoImage(Image.open('cardframe.jpg'))
vlabel.configure(image=photo)
vlabel.pack()
b2=tk.Button(root,text="Capture",command=lambda:change_pic(vlabel))
b2.pack()
root.mainloop()

我相信代码会在本地更改图像,因此全局语句将在项目范围内更改它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接