如果在函数中创建Tkinter图像,为什么不显示?

tho*_*ell 30 python image tkinter tkinter-canvas

此代码有效:

import tkinter

root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
canvas.create_image(0, 0, image=photo)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)

它向我展示了图像.

现在,这段代码编译但它没有显示我的图像,我不知道为什么,因为它是相同的代码,在类中:

import tkinter

class Test:
    def __init__(self, master):
        canvas = tkinter.Canvas(master)
        canvas.grid(row = 0, column = 0)
        photo = tkinter.PhotoImage(file = './test.gif')
        canvas.create_image(0, 0, image=photo)

root = tkinter.Tk()
test = Test(root)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)

Bry*_*ley 44

该变量photo是一个局部变量,它在实例化类之后获取垃圾.保存对照片的引用,例如:

self.photo = tkinter.PhotoImage(...)
Run Code Online (Sandbox Code Playgroud)

如果您在"tkinter图片无法显示"上进行Google搜索,则第一个结果如下:

http://effbot.org/pyfaq/why-do-my-tkinter-images-not-appear.htm

  • @TamasHegedus:我同意这是一个错误,但显然没有人在(目前)近二十年后费心去修复这个错误。我已经记不清有多少次看到有关它的问题仍然弹出。 (10认同)
  • 我发现了一张非常旧的票,已经关闭而没有修复:https://bugs.python.org/issue632323 (4认同)
  • @aru:这个例子展示了如何在不使用全局的情况下做到这一点。 (3认同)
  • 哇。他们认为这是 tkinter 中的错误吗?他们应该。 (2认同)
  • 该链接无法使用 atm,除了使用“global”之外还有其他方法吗? (2认同)
  • @Enderman:不,因为它引用了自己。对象需要对其进行外部引用,否则垃圾收集器可能会销毁它。 (2认同)

小智 9

from tkinter import *
from PIL import ImageTk, Image

root = Tk()

def open_img():
    global img
    path = r"C:\.....\\"
    img = ImageTk.PhotoImage(Image.open(path))
    panel = Label(root, image=img)
    panel.pack(side="bottom", fill="both")
but1 = Button(root, text="click to get the image", command=open_img)
but1.pack()
root.mainloop() 
Run Code Online (Sandbox Code Playgroud)

只需将 global 添加到 img 定义中即可工作

  • 这个答案对于只使用函数的程序来说很好,但是如果像OP的情况一样,你使用一个类,那么“global”就不是正确的选择。 (4认同)

Far*_*wle 8

问题是 Python 通过一个称为“垃圾收集”的过程自动删除对该变量的引用。解决方案是保存参考或创建新参考。

有以下几种方法:

  1. 用于self增加引用计数和保存引用。
import tkinter

class Test:
    def __init__(self, master):
        canvas = tkinter.Canvas(master)
        canvas.grid(row = 0, column = 0)
        self.photo = tkinter.PhotoImage(file = './test.gif') # Changes here
        canvas.create_image(0, 0, image=self.photo) # Changes here

root = tkinter.Tk()
test = Test(root)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)
  1. 将其保存到列表中以增加引用计数并保存引用。
import tkinter
l=[]
class Test:

    def __init__(self, master):
        canvas = tkinter.Canvas(master)
        canvas.grid(row = 0, column = 0)
        photo = tkinter.PhotoImage(file = './test.gif')
        l.append(photo)
        canvas.create_image(0, 0, image=photo)

root = tkinter.Tk()
test = Test(root)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)

使用方法 2 时,您可以像我一样创建一个全局列表,也可以在类中使用列表。两者都可以。

一些有用的链接: