Home > Enterprise >  Unable to display images in a stream in tkinter instead it prints all images on same page
Unable to display images in a stream in tkinter instead it prints all images on same page

Time:03-16

With the following code I want to display images from a relative path .\Datasets\image_datasets\problem_datasets within my project, I am unable to do so with tkinter, Instead it displays all the images in same UI window, I want these images to be displayed like a stream of frames as a video, can you help me understand why I don't get the expected ouput.

code :

import tkinter as tk
from PIL import ImageTk, Image
from matplotlib import image
from numpy import imag
import matplotlib.pyplot as plt
import glob

root = tk.Tk()
root.title("Test app")

images = [file for file in glob.glob('.\\Datasets\\image_datasets\\problem_datasets\\*.jpg')]

for path in images:
    img = ImageTk.PhotoImage(Image.open(path))
    lab = tk.Label(root,image=img)
    lab.photo = img
    lab.pack()

root.mainloop()

This is how it get's displayed

CodePudding user response:

You created new label in each iteration of the for loop. Instead you should create the label once before the for loop and update its image inside it.

However using loop and time.sleep() is not recommended in a tkinter application, suggest to use .after() instead:

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

root = tk.Tk()
root.title("Test app")

images = glob.glob('./Datasets/image_datasets/problem_datasets/*.jpg')

# create the label for showing the images
lab = tk.Label(root)
lab.pack()

def show_image(i=0):
    if i < len(images):
        img = ImageTk.PhotoImage(file=images[i])
        # update image
        lab.config(image=img)
        lab.photo = img # save reference of image to avoid garbage collection
        # can change 10(ms) to other value to suit your case
        root.after(10, show_image, i 1) 

show_image() # start showing the images
root.mainloop()

CodePudding user response:

A couple of points:

  • you dont need lab.photo = img
  • you need to define and pack the label outside of your loop and just overwrite the image property inside, otherwise you create new labels each iteration
  • i recommend using os.sep instead of hardcoded folder separators \\ to be OS-independent
  • to actually see the transition, you need time.sleep or similar
  • my example will freeze the GUI, if you want it to be reactive after launching your image-transitions/"video", you will have to implement Threads
import tkinter as tk
from PIL import ImageTk, Image
from matplotlib import image
from numpy import imag
import matplotlib.pyplot as plt
import glob
import os
import time

root = tk.Tk()
root.title("Test app")

images = [file for file in glob.glob('.'   os.sep   'Datasets'   os.sep   'image_datasets'   os.sep   'problem_datasets'   os.sep   '*.jpg')]

lab = tk.Label(root)
lab.pack()

for path in images:
    _img = ImageTk.PhotoImage(Image.open(path))
    lab.config(image=_img)
    root.update()  # to update the GUI
    time.sleep(0.25)  # to see the transition

root.mainloop()
  • Related