Home > OS >  Generate Tkinter Canvas In Loop with Image
Generate Tkinter Canvas In Loop with Image

Time:08-05

I'm attempting to create a series of canvases, each displaying a different section of an image according to the coordinates present in a list. The number of different coordinates is dynamic so it must be done in a loop.

The issue I am having is even though I'm saving my references garbage collection is preventing all canvases except the last from displaying an image.

Here is what I have so far:

import tkinter as tk
import cv2
from PIL import Image, ImageTk

class App(object):
    def __init__(self):
        self.root = tk.Tk()
        # Candidates holds the coordinates for the image sections, and is hardcoded for this example
        candidates = [[0,100,100,100], [15,15,200,200], [30,30,200,200], [50,50,200,200], [100,100,200,200], [200,200,200,200]]

        self.im = cv2.imread(r"....")

        j = 0
        i = 0
        frames = []
        images = []
        refs = []
        for candidate in candidates:
            x,y,w,h = tuple(candidate)
            self.img_tk = ImageTk.PhotoImage(Image.fromarray(self.im[y:y h, x:x w]))

            Frame = tk.Canvas(self.root,bg='white', highlightthickness=1, highlightbackground="black", width=100, height= 100)
            Frame.grid(row = i, column = j, sticky = 'w, e, n, s', padx=5, pady=5)
            ref = Frame.create_image(0, 0, image=self.img_tk, anchor="nw")
            
            images.append(self.img_tk)
            refs.append(ref)
            frames.append(Frame)

            if j<2: 
                j =1
            else: 
                j=0
                i =1

app = App()
app.root.mainloop()

and the result:

Result of tkinter code

As you can see, only the last frame in the loop has an image created. Any thoughts are greatly appreciated, thanks.

CodePudding user response:

It is because images is a local variable, so it will be garbage collected after the function exits, so are the image references stored in it. The last image can be shown because self.img_tk saves the reference.

To solve it, change images to instance variable self.images.

  • Related