Home > OS >  tkinter Image is not displayed unless the mainloop() is called in the same class
tkinter Image is not displayed unless the mainloop() is called in the same class

Time:11-21

I am new to tkinter and encounter this strange behavior with the images. Please pay attention to the *.mainloop() in the code below.


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

class BaseWindow(tk.Tk):
    def __init__(self):
        super(BaseWindow, self).__init__()
        self.geometry("800x700")
        self.title("test title")

        frame = ttk.Frame(self)
        frame.pack()
        ttk.Label(frame, text="test label").pack()
        img = ImageTk.PhotoImage(Image.open("res/male_avatar.png").resize(
            (200, 200)))
        ttk.Label(frame, image=img).pack()

        frame_parent = ttk.Frame(self)
        frame_parent.pack()

        ParentWindow(frame_parent, self)
        # self.mainloop()


class ParentWindow(ttk.Frame):
    def __init__(self, parent, app):
        super(ParentWindow, self).__init__(parent)
        self.pack()
        ttk.Label(self, text="parent label test").pack()

        img = ImageTk.PhotoImage(Image.open("res/male_avatar.png").resize(
            (200, 200)))
        ttk.Label(self, image=img).pack()
        ttk.Label(self, text="test label").pack()

        frame_child = ttk.Frame(self)
        frame_child.pack()

        ChildWindow(frame_child, app)
        # app.mainloop()


class ChildWindow(ttk.Frame):
    def __init__(self, parent, app):
        super(ChildWindow, self).__init__(parent)
        self.pack()
        ttk.Label(self, text="child label test").pack()

        img = ImageTk.PhotoImage(Image.open("res/male_avatar.png").resize(
            (200, 200)))
        ttk.Label(self, image=img).pack()
        ttk.Label(self, text="test label").pack()
        # app.mainloop()


if __name__ == '__main__':
    # BaseWindow().mainloop()
    BaseWindow()
    

There are three classes, but the image is created by each class is shown only if the mainloop() is called in the respective class.

All the other widgets work just fine regardless of where I call the mainloop() for instance the Label() widget as in example code below.

Only the images do not display if I don't call the mainloop() in the proper way.

Explaination

1.) if name == .............. in this block if I call the BaseWindow().mainloop() then everything works fine, all the widgets are displayed, but the images are not displayed. Images created in all the classes are not shown.

2.) class BaseWindow()....... if the self.mainloop() is called here then, one image i.e. image created in this class is shown/displayed and other images are not displayed.

3.) class ParentWindow().......... if the app.mainloop() is called here then, two images are displayed, i.e. the image created in the BaseWindow class and ParentWindow class are displayed.

4.) similarly the image in the ChildWindow() class is only displayed if the app.mainloop() is called in this class.

So, in order to display all the images, I need to call the mainloop in the last class, but in this way, I need to pass the app object to all the child classes. Isn't there a way to call mainloop only once in the app and get everything work.? How do I display the images by calling mainloop() only in the BaseWindow() class...?

CodePudding user response:

I beginner at this stuff but I think you do need all of those .mainloop() because it updates the UI. But I am not sure. Hope you get more answers!

CodePudding user response:

Here i have some thing for you. You can add a single line in child Window class and your problem will be solved.

class ChildWindow(ttk.Frame):
def __init__(self, parent, app):
    super(ChildWindow, self).__init__(parent)
    self.pack()
    ttk.Label(self, text="child label test").pack()

    img = ImageTk.PhotoImage(Image.open("COMSATS.png").resize((200, 200)))
    ttk.Label(self, image=img).pack()
    ttk.Label(self, text="test label").pack()
    self.mainloop()

Add self.mainloop() at the end of last class you have to visit.

self.mainloop()

Then,

if __name__ == '__main__':
BaseWindow()

All the images will be displayed at once.

  • Related