无法在主循环中创建新图像

时间:2018-11-02 23:04:52

标签: python tkinter python-imaging-library

我有一长串要加载到Tkinter画布中的图像。

我发现,如果我在Tkinter实例上调用PIL.PhotoImage之前创建mainloop实例,则此方法有效。我将以下内容绑定到与按键或类似事件绑定的回调函数中:

def onkeypress( event )
  canvas.itemconfig( canvas_image, image_content )

image_content = PIL.PhotoImage( file="myfile.jpg" )
mytk.bind( "<Key>", onkeypress )
mytk.mainloop()

...但是这要求我在启动主循环之前将整个图像库加载到内存中。如果我尝试仅根据需要创建每个PIL.PhotoImage

def onkeypress( event )
  image_content = PIL.PhotoImage( file="myfile.jpg" )
  canvas.itemconfig( canvas_image, image_content )

mytk.bind( "<Key>", onkeypress )
mytk.mainloop()

然后代码执行时没有给我错误,但是我看不到画布内容更改。

我需要怎么做才能更改画布内容?

2 个答案:

答案 0 :(得分:1)

第一个问题是我可以在mainloop()之后看到它的功能。在关闭tkinter实例之前,您无法在mainloop之后运行任何操作。因此,您将需要将函数移至mainloop以及绑定上方。另一个重要的问题是函数中的局部变量。您的函数创建了一个本地图像,该图像将在函数完成后消失,因此您需要在函数中将image_content定义为全局图像。

在使用画布时也适用相同的规则,因此,如果以我下面的示例为例,也可以将其应用于您的需求。

这是一个简单的示例,说明了如何将引用也保存为图像,并在需要时随时使用按钮应用它们。

import tkinter as tk
from PIL import ImageTk


root = tk.Tk()

def change_color(img_path):
    global current_image
    current_image = ImageTk.PhotoImage(file=img_path)
    lbl.config(image=current_image)


current_image = ImageTk.PhotoImage(file="red.gif")
lbl = tk.Label(root, image=current_image)
lbl.grid(row=0, column=0, columnspan=3)

tk.Button(root, text="RED", command=lambda: change_color("red.gif")).grid(row=1, column=0)
tk.Button(root, text="BLUE", command=lambda: change_color("blue.gif")).grid(row=1, column=1)
tk.Button(root, text="GREEN", command=lambda: change_color("green.gif")).grid(row=1, column=2)

root.mainloop()

结果:

enter image description here enter image description here enter image description here

答案 1 :(得分:-1)

这是因为tk不会保存该图像对象的引用,因此GC将在函数作用域之后收集它,因为image_content是最后一个引用,并且它消失了。

您可以通过长期参考轻松解决此问题。