Why won't my Label containing pyimage1 image object pack and display on the frame, when other labels containing text will?

Question:

I am trying to display the image passed from the MainFrame class to the CheckImageFrame class using the open_file and switch_frame methods. The object is a PIL PhotoImage/pyimage1 object.

I would like to understand why the Label with the "this is page one" text in the CheckImageFrame class will pack successfully, but the image will not.

Thanks in advance!

class WaterMarkGenerator(Tk):
    def __init__(self):
        Tk.__init__(self)
        self._frame = None
        self.switch_frame(MainFrame)

    def switch_frame(self, frame_class, image=None):
        # Destroys the current frame and replaces it with a new frame
        new_frame = frame_class(self, image)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.pack()
        

class MainFrame(Frame):
    def __init__(self, master, image):
        Frame.__init__(self, master)
        master.title("Watermark Generator")
        Label(self, text="Please upload an image to watermark.").pack(pady=30)
        Button(self, text='Upload a File', command=self.open_file).pack(expand=True)

    def open_file(self):
        self.file_path = filedialog.askopenfilename(
            initialdir='/',
            filetypes = (
                ('JPEG', '*.jpg'),
                ('PNF', '*.png'),
                ('All files', '*.*')
            )
        )
        if self.file_path is not None:
            try:
                self.image = Image.open(self.file_path, mode='r')
                self.tkinter_image = ImageTk.PhotoImage(self.image)
                self.master.switch_frame(CheckImageFrame, image=self.tkinter_image)
            except IOError:
                pop_up_window()


class CheckImageFrame(Frame):
    def __init__(self, master, image):
        Frame.__init__(self, master)
        Label(self, text="This is page one").pack(fill="x", pady=10)
        Label(self, image=image).pack(fill='x', pady=50)
Asked By: ALHComer

||

Answers:

You need to keep a reference to the image inside CheckImageFrame so it is not collected by pythons garbage collector:

class CheckImageFrame(Frame):
    def __init__(self, master, image):
        Frame.__init__(self, master)

        self.image = image # Keep reference
        Label(self, text="This is page one").pack(fill="x", pady=10)
        Label(self, image=image).pack(fill='x', pady=50)

I posted an answer even though this is a duplicate of the popular question, Why does Tkinter image not show up if created in a function?, because the implementation of that answer here could be tricky as the image seems to have reference in all the other classes except CheckImageFrame.

Alternatively:

class WaterMarkGenerator(Tk):
    def __init__(self):
        ...
        ...

    def switch_frame(self, frame_class, image=None):
        # Destroys the current frame and replaces it with a new frame
        self.image = image # Hold a reference here itself
        new_frame = frame_class(self, self.image)
        ...
Answered By: Delrius Euphoria
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.