如何无需先打开任意图片即可使用ImageTk.getimage?
问题:ImageTk.getimage调用失败,提前调用一次ImageTk.PhotoImage则恢复正常
调用ImageTk.getimage处理图片时触发如下错误:
line 279, in getimage
photo.tk.call("PyImagingPhotoGet", photo, block.id)
tkinter.TclError: invalid command name "PyImagingPhotoGet"
奇怪的是:如果先对任意图片执行一次ImageTk.PhotoImage调用,后续ImageTk.getimage就能正常工作。
以下是可复现问题的示例代码:
from tkinter import * from PIL import ImageTk, Image import os gamma_code = 'R0lGODlhCgAMAIcAAP///9v//4/b////22a2////trZmAN' gamma_code += 'uPOTmP29vb/wAAALb//7aPj7ZmZrZmOf+2Zo+2j49mj485' gamma_code += 'OY85AP/bj2ZmOWYAOWYAANv/2zk5jzkAAABmtgA5jwAAZg' for k in range(90) : gamma_code += 'AAAAAAAAAA' gamma_code += 'AAACH5BAEAAAAALAAAAAAKAAwAAAhgAAEIHEgQAAUNHRYA' gamma_code += 'OKCAAAAADDBIEFDgAgEAAAYkAGCAwIENAEKKdAAhQwAAKF' gamma_code += 'M2qCAAgMuXAAwgAECzJoABEQIA2MkTwAMOAQAIHTpgAgIA' gamma_code += 'SJMCKGBBAICnUKNKBRAQADs=' LAMBDA_code = 'R0lGODlhDQANAIcAAP///wAAAP//ttuPOWYAAP+2Zo/b/' LAMBDA_code += '2a2/9v//wAAOQBmtrb//wA5j485AP//2//bj7ZmAI85Zm' LAMBDA_code += 'ZmtrZmOTmP2zmPtjk5jwAAZgAAAAAAA' for m in range(92) : LAMBDA_code += 'AAAAAAAAAA' LAMBDA_code += 'CH5BAEAAAAALAAAAAANAA0AAAiDAAEIHEiw4EABEgAoXM' LAMBDA_code += 'gQwIALCwBInDjRQYMABwBo3LixQIUGDBAAGEly5AQDAxI' LAMBDA_code += 'YAMCyJYAHFhAIIEABgM2bAAYcAAAAAgMEAIIGdRBhAQAA' LAMBDA_code += 'BQIcAMCUaQEFAKIKIKAAgFUAAggcAMAVwIAEBgAAEEAgQ' LAMBDA_code += 'AIDAAAUCMBWAYC3cOPGDQgAOw==' def test(IM) : try : ImageTk.getimage(IM) print('SUCCESS') except : print('FAILURE') root = Tk() A = PhotoImage(data = gamma_code) print('image 1 dimensions : ',A.width(),',',A.height()) B = PhotoImage(data = LAMBDA_code) print('image 2 dimensions : ',B.width(),',',B.height()) temp_file_name = 'wlqdkijqodmqqx9.f4r' #random digits B.write(temp_file_name) print('\nattempt 1 : ', end = "") test(A) ImageTk.PhotoImage(Image.open(temp_file_name)) print("\n'ImageTk.PhotoImage(Image.open(temp_file_name))' has now been run.") print('attempt 2 : ', end = "") test(A) os.remove(temp_file_name)
原因与解决方法
原因
ImageTk.getimage依赖的Tcl命令PyImagingPhotoGet并未在程序启动时自动注册。只有当第一次调用ImageTk.PhotoImage时,模块才会完成Tcl扩展的初始化,注册该命令,后续getimage才能正常调用。
解决方案
不需要实际加载图片,只需提前触发ImageTk的初始化逻辑即可。在程序启动阶段添加以下代码:
from tkinter import Tk from PIL import ImageTk root = Tk() # 触发ImageTk的Tcl扩展初始化 ImageTk._get_image_tk(root)
或者更简单的方式,直接调用一次空的ImageTk.PhotoImage(无需传入图片),但_get_image_tk方法更直接对应初始化逻辑,推荐使用。
执行一次初始化后,后续所有ImageTk.getimage调用都会正常工作,无需再临时调用PhotoImage。
内容的提问来源于stack exchange,提问作者agat
相关产品推荐
相关产品推荐

