Python Tkinter画布多次创建图像

Python Tkinter画布多次创建图像,python,canvas,tkinter,tkinter-canvas,Python,Canvas,Tkinter,Tkinter Canvas,我在代码中使用此函数在画布上创建图像: def _create_image(self, coord): (x,y) = coord self.one = ImageTk.PhotoImage(Image.open("test.jpg")) root.one = self.one self.canvas.create_image(x-25, y-25, image=self.one, anchor='nw', tags="image") 我的问题是,每次调用此函

我在代码中使用此函数在画布上创建图像:

def _create_image(self, coord):
    (x,y) = coord 
    self.one = ImageTk.PhotoImage(Image.open("test.jpg"))
    root.one = self.one
    self.canvas.create_image(x-25, y-25, image=self.one, anchor='nw', tags="image")
我的问题是,每次调用此函数时,旧图像都会被删除,并创建一个新图像


如何防止删除旧图像?我想在画布上多次创建该图像。

image.open()
每次都将重写该图像。

image.open()
每次都将重写该图像。

首先在中创建一个列表,例如
\uu init\uuuuuu()

然后在创建新图像时将其附加到此列表:

def _create_image(self, coord):
    (x,y) = coord 
    self.one = ImageTk.PhotoImage(Image.open("test.jpg"))
    root.one = self.one
    self.canvas.create_image(x-25, y-25, image=self.one,
                             anchor='nw', tags="image")
    self.img_ref.append(self.one)  # Keep reference to image

即使每个图像都是相同的图像,您也必须保留对每个图像的引用。

首先在例如
\uuuu init\uuuu()中创建一个列表。

然后在创建新图像时将其附加到此列表:

def _create_image(self, coord):
    (x,y) = coord 
    self.one = ImageTk.PhotoImage(Image.open("test.jpg"))
    root.one = self.one
    self.canvas.create_image(x-25, y-25, image=self.one,
                             anchor='nw', tags="image")
    self.img_ref.append(self.one)  # Keep reference to image

即使每个图像都是相同的图像,您也必须保留对每个图像的引用。

您不需要修改
\uuu init\uuu()
方法,也不需要存储引用列表,因为它始终是相同的图像文件。在这里,可以避免使用不必要的资源,因此可以使用更少的内存(而且可能更快)

它通过测试查看
one
属性是否已经存在来实现这一点,如果不存在,则只读取图像数据并第一次创建
PImageTk.PhotoImagehotoImage

这种方法允许您从相同的
ImageTk.PhotoImage
创建多个
Canvas
窗口小部件图像对象,而不是将其多个副本加载到内存中

def _create_image(self, coord):
    (x,y) = coord

    if not getattr(self, 'one', None):  # First call?
        pil_img = Image.open("test.jpg")
        self.one = ImageTk.PhotoImage(pil_img)

    self.canvas.create_image(x-25, y-25, image=self.one,
                             anchor='nw', tags="image")
您还可以在一行中创建
ImageTk.PhotoImage

    # pil_img = Image.open("test.jpg")  # Leave out.
    self.one = ImageTk.PhotoImage(file="test.jpg")

无需修改
\uuuu init\uuuu()
方法,也无需存储引用列表,因为它始终是相同的图像文件。在这里,可以避免使用不必要的资源,因此可以使用更少的内存(而且可能更快)

它通过测试查看
one
属性是否已经存在来实现这一点,如果不存在,则只读取图像数据并第一次创建
PImageTk.PhotoImagehotoImage

这种方法允许您从相同的
ImageTk.PhotoImage
创建多个
Canvas
窗口小部件图像对象,而不是将其多个副本加载到内存中

def _create_image(self, coord):
    (x,y) = coord

    if not getattr(self, 'one', None):  # First call?
        pil_img = Image.open("test.jpg")
        self.one = ImageTk.PhotoImage(pil_img)

    self.canvas.create_image(x-25, y-25, image=self.one,
                             anchor='nw', tags="image")
您还可以在一行中创建
ImageTk.PhotoImage

    # pil_img = Image.open("test.jpg")  # Leave out.
    self.one = ImageTk.PhotoImage(file="test.jpg")

感谢马蒂诺在这件事上的贡献。如果将ImageTk变量分开使用而不重复使用,它似乎可以工作。否则,即使是新实例,它们也会保持相同的文件路径。通过保持ImageTk的独立变量,我成功地将多个不同的图像绘制到画布上

    from PIL import Image, ImageTk
    import tkinter as tk
    from tkinter.filedialog import askopenfilename


    root = tk.Tk 
    root.mainloop()

    self.ph = [] #keep photoimage instances separate
    
    def appendImages(self):  #Call appendImages as many times as needed
        path = askopenfilename(initialdir="/", title="Select file",  filetypes(("all files", "*.*"),("jpeg files", ".jpg")))
        im = Image.open(path)
        self.ph.append(ImageTk.PhotoImage(im))
        self.canvasImage=self.canvas.create_image(x,y,anchor=NW,image=self.ph[len(self.ph)-1])

最后一行绘制了用户最近拍摄的图像

,感谢Martineau在这张图像上的输入。如果将ImageTk变量分开使用而不重复使用,它似乎可以工作。否则,即使是新实例,它们也会保持相同的文件路径。通过保持ImageTk的独立变量,我成功地将多个不同的图像绘制到画布上

    from PIL import Image, ImageTk
    import tkinter as tk
    from tkinter.filedialog import askopenfilename


    root = tk.Tk 
    root.mainloop()

    self.ph = [] #keep photoimage instances separate
    
    def appendImages(self):  #Call appendImages as many times as needed
        path = askopenfilename(initialdir="/", title="Select file",  filetypes(("all files", "*.*"),("jpeg files", ".jpg")))
        im = Image.open(path)
        self.ph.append(ImageTk.PhotoImage(im))
        self.canvasImage=self.canvas.create_image(x,y,anchor=NW,image=self.ph[len(self.ph)-1])

最后一行绘制用户拾取的最新图像

完美的可能副本的可能副本!非常感谢,太好了!非常感谢。多次调用
Image.open()
不会重写任何内容,每次都会返回一个新的PIL Image对象。@martineau啊,是的,我很抱歉,我一定把这与其他内容混淆了调用
Image.open()
多次不会重写任何内容,每次它都会返回一个新的PIL图像对象。@martineau啊,是的,我很抱歉,我一定是把它和其他东西混淆了