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

Tkinter OptionMenu点击触发PIL图片生成失效问题求助

Tkinter OptionMenu调用图片生成函数时显示空白的解决方法

我开发了一款通过参数生成图片的Tkinter应用,遇到一个问题:当把show(event)作为OptionMenu的command使用时,生成的图片显示为空白矩形;但直接执行图片生成代码却能正常显示。

有问题的完整代码

# 导入库
from tkinter import *
from PIL import Image, ImageTk, ImageFont, ImageDraw

win=Tk()
win.geometry("700x550")

# 加载图片文件
thusday=Image.open("E:\спм суд\ЧТ.png")
olus=Image.open('E:\спм суд\ОЛУС.png')

# 处理函数
def show(event):
    if clicked.get()=='ОЛУС':
        Label(win, text='ОЛУСС').pack()
        img=Image.alpha_composite(olus, thusday)
        new_width  = int(500)
        new_height = int(new_width * 1080 / 1920) 

        resized_image=img.resize((new_width,new_height), Image.LANCZOS)
        img = ImageTk.PhotoImage(resized_image)
        Label(win,image=img).pack(pady=20)
    Label(win, text=clicked.get()).pack()

# 选项列表
cities=[
    'ОЛУС', 
    'БАРСЕЛОНА', 
    'СПАВН', 
    'НЕГОРОД КВАТОСА'
]       

day=[
    'Четверг', 
    'Воскресенье'
]    

# 下拉菜单
clicked=StringVar()
clicked.set('город проведения')
drop=OptionMenu(win, clicked, *cities, command=show)
drop.pack()

click=StringVar()
click.set('день недели')
drop=OptionMenu(win, click, *day)
drop.pack()

# 按钮(注释掉的)
##Boobs=Button(win, text="GENERATE", command=show).pack()

可正常运行的代码片段

thusday=Image.open("E:\спм суд\ЧТ.png")
olus=Image.open('E:\спм суд\ОЛУС.png')

img=Image.alpha_composite(olus, thusday)
new_width  = int(500)
new_height = int(new_width * 1080 / 1920) 
resized_image=img.resize((new_width,new_height), Image.LANCZOS)
img = ImageTk.PhotoImage(resized_image)
Label(win,image=img).pack(pady=20)

问题原因

问题核心是Python垃圾回收机制:在show函数中,img是局部变量,函数执行完毕后会被垃圾回收器销毁。而Tkinter的PhotoImage对象需要持续存在的引用才能在Label中显示,没有引用时会被回收,导致标签显示空白。直接执行代码时,img是全局变量,不会被立即回收,因此能正常显示。

解决方案

有两种可靠的解决方式:

1. 将img声明为全局变量

修改show函数,在创建PhotoImage前添加global img声明,让变量成为全局引用:

def show(event):
    global img  # 声明为全局变量
    if clicked.get()=='ОЛУС':
        Label(win, text='ОЛУСС').pack()
        img=Image.alpha_composite(olus, thusday)
        new_width  = int(500)
        new_height = int(new_width * 1080 / 1920) 

        resized_image=img.resize((new_width,new_height), Image.LANCZOS)
        img = ImageTk.PhotoImage(resized_image)
        Label(win,image=img).pack(pady=20)
    Label(win, text=clicked.get()).pack()

2. 将img绑定到Label对象的属性上

创建Label后,把img赋值给Label的自定义属性,让Label持有对img的引用:

def show(event):
    if clicked.get()=='ОЛУС':
        Label(win, text='ОЛУСС').pack()
        img=Image.alpha_composite(olus, thusday)
        new_width  = int(500)
        new_height = int(new_width * 1080 / 1920) 

        resized_image=img.resize((new_width,new_height), Image.LANCZOS)
        img = ImageTk.PhotoImage(resized_image)
        img_label = Label(win, image=img)
        img_label.img = img  # 绑定引用到Label属性
        img_label.pack(pady=20)
    Label(win, text=clicked.get()).pack()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 12:07:48