【问题标题】:Tkinter canvas create image multiple timesTkinter 画布多次创建图像
【发布时间】:2018-11-16 20:45:38
【问题描述】:

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

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")

我的问题是每次我调用这个函数都会删除旧图像并创建一个新图像。

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

【问题讨论】:

标签: python canvas tkinter tkinter-canvas


【解决方案1】:

首先创建一个列表,例如__init__()

self.img_ref = []

然后在创建它们时将每个新图像附加到此列表中:

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

即使每张图片都是同一张图片,您也必须保留对每张图片的引用。

【讨论】:

  • 完美!非常感谢。
【解决方案2】:

不需要修改__init__() 方法,也不需要存储引用列表,因为它始终是同一个图像文件。这里避免使用不必要的资源,因此会使用更少的内存(并且可能更快)。

它通过测试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")

【讨论】:

    【解决方案3】:

    感谢 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])
    

    最后一行绘制了用户最近挑选的图像

    【讨论】:

    • 这很好用。正是我想要的。
    【解决方案4】:

    Image.open() 每次都会重写图片。

    【讨论】:

    • 多次调用Image.open()不会重写任何东西,每次都会返回一个新的PIL图像对象。
    • @martineau 啊,是的,我很抱歉,我一定把它和别的东西弄混了
    猜你喜欢
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 2021-05-04
    • 2021-05-31
    相关资源
    最近更新 更多