在 Tk.Canvas 中制作新的 Pillow 图像时,为什么数组有效但变量无效?
When making a new Pillow image in Tk.Canvas, why does an array work but not a variable?
我正在尝试在 Tkinter 中创建一个半透明 (RGBA) 矩形。我使用 中的代码片段来制作它,但我无法理解数组在这里的作用。他们最初想制作多个矩形,所以我理解为什么他们会在这方面使用它,但是当我尝试将数组更改为一个变量时,根据我的理解,它会做同样的事情,它停止显示矩形颜色。
这是(稍作修改的)代码,其中包含用于输出的数组:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
images = [] # to hold the newly created image
def create_rectangle(x1, y1, x2, y2, **kwargs): # x & y's dimensions
alpha = int(kwargs.pop('alpha') * 255)
fill = kwargs.pop('fill')
fill = root.winfo_rgb(fill) + (alpha,) # Returns a tuple of the color
image = Image.new('RGBA', (x2-x1, y2-y1), fill)
images.append(ImageTk.PhotoImage(image))
canvas.create_image(x1, y1, image=images[-1], anchor='nw')
canvas.create_rectangle(x1, y1, x2, y2, **kwargs)
canvas = Canvas(width=300, height=300)
canvas.pack()
create_rectangle(50, 50, 250, 150, fill='green', alpha=.5)
root.mainloop()
其输出:
并且在 image=
之后使用变量代替 images[-1]
的相同代码:
def create_rectangle(x1, y1, x2, y2, **kwargs): # x & y's dimensions
alpha = int(kwargs.pop('alpha') * 255)
fill = kwargs.pop('fill')
fill = root.winfo_rgb(fill) + (alpha,) # Returns a tuple of the color
image = Image.new('RGBA', (x2-x1, y2-y1), fill)
test_var = ImageTk.PhotoImage(image)
canvas.create_image(x1, y1, image=test_var, anchor='nw')
canvas.create_rectangle(x1, y1, x2, y2, **kwargs)
输出:
如果我打印两者的 type()
,我会得到相同的结果 (<class 'PIL.ImageTk.PhotoImage'>
),定义相同的变量并附加它 (images.append(test_var)
) 会得到正确的结果.只有在canvas.create_image
中使用变量时才会出现错误。
有谁知道发生了什么事吗?
PhotoImage
中存在错误 - Garbage Collector
在将 PhotoImage
分配给局部变量时从内存中删除,然后您看到空图像。
您必须将其分配给 global
变量
def create_rectangle(...):
global test_var
# ... code ...
test_var = ...
# ... code ...
或者您可以将其分配给其他对象。
将它分配给一些将显示它的小部件很流行(Canvas
、Label
、Button
)。
def create_rectangle(...):
# ... code ...
test_var = ...
canvas.test_var = test_var
# ... code ...
请参阅 PhotoImage
的文档中的 Note
import tkinter as tk # PEP8: `import *` is not preferred
from PIL import Image, ImageTk
# --- classes ---
# ... empty ...
# --- functions ---
def create_rectangle(x1, y1, x2, y2, **kwargs): # x & y's dimensions
#global photo
alpha = int(kwargs.pop('alpha') * 255)
fill = kwargs.pop('fill')
fill = root.winfo_rgb(fill) + (alpha,) # Returns a tuple of the color
image = Image.new('RGBA', (x2-x1, y2-y1), fill)
photo = ImageTk.PhotoImage(image)
#images.append(photo)
canvas.photo = photo
canvas.create_image(x1, y1, image=photo, anchor='nw')
canvas.create_rectangle(x1, y1, x2, y2, **kwargs)
# --- main ---
#images = [] # to hold the newly created image
root = tk.Tk()
canvas = tk.Canvas(width=300, height=300)
canvas.pack()
create_rectangle(50, 50, 250, 150, fill='green', alpha=.5)
root.mainloop()
PEP 8 -- Style Guide for Python Code
编辑:
正如@acw1668 在评论中提到的那样:如果您将 运行 create_rectangle
多次,那么它会将新图像分配给 global
变量或 canvas.photo
和 Garbage Collector
将从内存中删除以前的图像,图像将消失。因此,如果您需要显示所有图像,请将它们全部保留在列表中。
我正在尝试在 Tkinter 中创建一个半透明 (RGBA) 矩形。我使用
这是(稍作修改的)代码,其中包含用于输出的数组:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
images = [] # to hold the newly created image
def create_rectangle(x1, y1, x2, y2, **kwargs): # x & y's dimensions
alpha = int(kwargs.pop('alpha') * 255)
fill = kwargs.pop('fill')
fill = root.winfo_rgb(fill) + (alpha,) # Returns a tuple of the color
image = Image.new('RGBA', (x2-x1, y2-y1), fill)
images.append(ImageTk.PhotoImage(image))
canvas.create_image(x1, y1, image=images[-1], anchor='nw')
canvas.create_rectangle(x1, y1, x2, y2, **kwargs)
canvas = Canvas(width=300, height=300)
canvas.pack()
create_rectangle(50, 50, 250, 150, fill='green', alpha=.5)
root.mainloop()
其输出:
并且在 image=
之后使用变量代替 images[-1]
的相同代码:
def create_rectangle(x1, y1, x2, y2, **kwargs): # x & y's dimensions
alpha = int(kwargs.pop('alpha') * 255)
fill = kwargs.pop('fill')
fill = root.winfo_rgb(fill) + (alpha,) # Returns a tuple of the color
image = Image.new('RGBA', (x2-x1, y2-y1), fill)
test_var = ImageTk.PhotoImage(image)
canvas.create_image(x1, y1, image=test_var, anchor='nw')
canvas.create_rectangle(x1, y1, x2, y2, **kwargs)
输出:
如果我打印两者的 type()
,我会得到相同的结果 (<class 'PIL.ImageTk.PhotoImage'>
),定义相同的变量并附加它 (images.append(test_var)
) 会得到正确的结果.只有在canvas.create_image
中使用变量时才会出现错误。
有谁知道发生了什么事吗?
PhotoImage
中存在错误 - Garbage Collector
在将 PhotoImage
分配给局部变量时从内存中删除,然后您看到空图像。
您必须将其分配给 global
变量
def create_rectangle(...):
global test_var
# ... code ...
test_var = ...
# ... code ...
或者您可以将其分配给其他对象。
将它分配给一些将显示它的小部件很流行(Canvas
、Label
、Button
)。
def create_rectangle(...):
# ... code ...
test_var = ...
canvas.test_var = test_var
# ... code ...
请参阅 PhotoImage
的文档中的Note
import tkinter as tk # PEP8: `import *` is not preferred
from PIL import Image, ImageTk
# --- classes ---
# ... empty ...
# --- functions ---
def create_rectangle(x1, y1, x2, y2, **kwargs): # x & y's dimensions
#global photo
alpha = int(kwargs.pop('alpha') * 255)
fill = kwargs.pop('fill')
fill = root.winfo_rgb(fill) + (alpha,) # Returns a tuple of the color
image = Image.new('RGBA', (x2-x1, y2-y1), fill)
photo = ImageTk.PhotoImage(image)
#images.append(photo)
canvas.photo = photo
canvas.create_image(x1, y1, image=photo, anchor='nw')
canvas.create_rectangle(x1, y1, x2, y2, **kwargs)
# --- main ---
#images = [] # to hold the newly created image
root = tk.Tk()
canvas = tk.Canvas(width=300, height=300)
canvas.pack()
create_rectangle(50, 50, 250, 150, fill='green', alpha=.5)
root.mainloop()
PEP 8 -- Style Guide for Python Code
编辑:
正如@acw1668 在评论中提到的那样:如果您将 运行 create_rectangle
多次,那么它会将新图像分配给 global
变量或 canvas.photo
和 Garbage Collector
将从内存中删除以前的图像,图像将消失。因此,如果您需要显示所有图像,请将它们全部保留在列表中。