You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter Canvas图片无法显示求助(代码无报错但图片不渲染)

Tkinter Canvas Doesn't Display Image (No Errors Thrown)

Question

I'm learning to implement basic animations with Python and tried inserting an image into a Tkinter Canvas component. The code runs without errors, but the image doesn't show up—though the polygon I created displays just fine. I need to display the image on the Canvas, not in a Label.

Here's my code:

from tkinter import *
import time
from PIL import *
def initiate():
    canvas1 = Canvas(root, width=800, height=600)
    canvas1.pack(expand=YES, fill=BOTH)
    im = PhotoImage(file='flag.gif', height=100, width=100)
    canvas1.create_polygon(10, 10, 0, 20, 20, 20, fill='white')
    print("hi")
    canvas1.create_image(100, 100, image=im)
    print('bye')
    root.update()
root = Tk()
initiate()
root.mainloop()

Answer

This is a super common gotcha with Tkinter's PhotoImage! Let's break down what's happening and how to fix it:

Why the Image Isn't Showing

The problem boils down to Python's garbage collection and how Tkinter handles image references. Your im variable is a local variable inside the initiate() function. Once the function finishes running, Python cleans up local variables—including im. Tkinter's Canvas doesn't keep its own reference to the PhotoImage object, so when im gets deleted, the image data is gone, and nothing displays on the Canvas.

Also, you imported PIL but aren't using it here—since you're working with a GIF (which Tkinter supports natively), that's not the issue right now, but it's worth noting for future image formats like PNG/JPG.

Fixes You Can Try

I recommend the second option below, as it's cleaner and avoids global variables:

1. Make im a Global Variable

By declaring im as a global variable, you ensure it doesn't get cleaned up when the function ends:

from tkinter import *
import time
from PIL import *

def initiate():
    global im  # Mark as global
    canvas1 = Canvas(root, width=800, height=600)
    canvas1.pack(expand=YES, fill=BOTH)
    im = PhotoImage(file='flag.gif', height=100, width=100)
    canvas1.create_polygon(10, 10, 0, 20, 20, 20, fill='white')
    canvas1.create_image(100, 100, image=im)
    root.update()

root = Tk()
initiate()
root.mainloop()

2. Bind the Image to the Canvas Object

A better approach is to attach the PhotoImage to a property of the Canvas itself. This way, the Canvas's reference to the image keeps it from being garbage collected:

from tkinter import *
import time
from PIL import *

def initiate():
    canvas1 = Canvas(root, width=800, height=600)
    canvas1.pack(expand=YES, fill=BOTH)
    im = PhotoImage(file='flag.gif', height=100, width=100)
    canvas1.image = im  # Store the image as a canvas attribute
    canvas1.create_polygon(10, 10, 0, 20, 20, 20, fill='white')
    canvas1.create_image(100, 100, image=im)
    root.update()

root = Tk()
initiate()
root.mainloop()

3. Use PIL's ImageTk (For Wider Image Format Support)

If you plan to work with non-GIF images later (like PNG or JPG), use PIL's Image and ImageTk modules. Just remember to still keep a reference to the image object:

from tkinter import *
import time
from PIL import Image, ImageTk  # Import the correct PIL modules

def initiate():
    canvas1 = Canvas(root, width=800, height=600)
    canvas1.pack(expand=YES, fill=BOTH)
    # Open and resize the image with PIL
    img = Image.open('flag.gif')
    img = img.resize((100, 100))
    im = ImageTk.PhotoImage(img)
    canvas1.image = im  # Keep the reference
    canvas1.create_polygon(10, 10, 0, 20, 20, 20, fill='white')
    canvas1.create_image(100, 100, image=im)
    root.update()

root = Tk()
initiate()
root.mainloop()

内容的提问来源于stack exchange,提问作者Kartik Narang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:09:44