Search code examples
pythontkinterpython-imaging-librarytkinter-label

How to display images from a directory as labels in Tkinter?


I'm new to Python GUI using Tkinter, and I'm stuck with the following:

I'm trying to read some image files in a particular directory using Python's os module, and show them as labels of Tkinter in a single window. The images have an average size of 1990 x 1200. So, I resized them using the Pillow library, and then packed every image to the window using a for loop.

But instead of showing the images, it's showing a blank window. I wrote the following code:

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

root = tk.Tk()
root.title("Photo Gallery")
root.geometry("655x350")

for (root_, dirs, files) in os.walk("Wallpaper"):
    if files:
        for file_ in files:
            path = os.path.join("Wallpaper", file_)
            image_ = Image.open(path)
            n_image = image_.resize((100, 100))
            photo = ImageTk.PhotoImage(n_image)
            img_label = tk.Label(root, image=photo)
            img_label.pack()


root.mainloop()

That's a screenshot of the blank window:

The image of the blank window.

Note: I use Python 3.6.3 and Pillow 8.2.0.


Solution

  • EDIT: Incorporating the hint from the comment of acw1668 (thanks for that!), the fix can be even more easier:

    for (root_, dirs, files) in os.walk("path/to/your/images"):
        if files:
            for file_ in files:
                path = os.path.join("path/to/your/images", file_)
                image_ = Image.open(path)
                n_image = image_.resize((100, 100))
                photo = ImageTk.PhotoImage(n_image)
                img_label = tk.Label(root, image=photo)
                img_label.photo = photo                             # <--
                img_label.pack()
    

    I suppose it's an issue regarding the garbage collection of the images, cf. this Q&A. Simply keeping some references to the single photo variables did the trick for me:

    references = []                                                 # <--
    for (root_, dirs, files) in os.walk("path/to/your/images"):
        if files:
            for file_ in files:
                path = os.path.join("path/to/your/images", file_)
                image_ = Image.open(path)
                n_image = image_.resize((100, 100))
                photo = ImageTk.PhotoImage(n_image)
                img_label = tk.Label(root, image=photo)
                img_label.pack()
                references.append(photo)                            # <--
    

    That's some output:

    Output

    ----------------------------------------
    System information
    ----------------------------------------
    Platform:      Windows-10-10.0.16299-SP0
    Python:        3.9.1
    PyCharm:       2021.1
    Pillow:        8.2.0
    ----------------------------------------