-1

So, my goal is to create a sort of slideshow within Tkinter. I have a list of images like Images = ["1.png", "2.png", ...], I want to be able to iterate through the list and display each image in a Tkinter window, the concept is simple and as follows:

  • Display Image 1
  • 30 Second Delay
  • Display Image 2
  • 30 Second Delay
  • Display Image 3

I have managed to iterate the images using a button press, however, I do not want to have to click a button as it is meant to imitate a slideshow, I also attempted looping a function but the time.sleep() function does not delay in the correct way because of how Tkinter behaves.

I managed to achieve the above using mostly source code from here, and I would appreciate a little hand achieving the above.

My Code:

from tkinter import *
from PIL import ImageTk, Image

Window = Tk()
Window.geometry("1920x1080")
Window.resizable(0, 0)

Label1 = Label(Window)
Label1.pack()

Images = iter(["1.png", "2.png", "3.png", "4.png", "5.png", 
         "6.png", "7.png", "8.png", "9.png", "10.png"])

def Next_Image(Val):
    try:
        Image1 = next(Images)
    except StopIteration:
        return

    Image1 = ImageTk.PhotoImage(Image.open(Image1))
    Label1.Image = Image1
    Label1["image"] = Image1

Button1 = Button(text = "Next image", command = 
lambda:Next_Image(1))
Button1.place(x = 50, y = 50)

Next_Image(1)

Window.mainloop()

I also attempted to use .after(), however, it did not display each image, it skipped from the first image to the last straight away with the compounded delay.

for x in range(1, 11):

    Window.after(1000, lambda : Next_Image(1))
  • Questions seeking debugging help (**"why isn't this code working?"**) should include the desired behavior, *a specific problem or error* and *the shortest code necessary* to reproduce it *as formatted text* (not images) **in the question itself**. Questions without **a clear problem statement** are not useful to other readers. See: [mre]. – MattDMo Dec 23 '21 at 00:39
  • @MattDMo Are you saying that my question does not give enough context, as I thought it covered it pretty clearly, I even included code that mine is based on from another post. – Shamus Wood Dec 23 '21 at 00:42
  • You didn't include any code at all. You linked to another question that contains some code, but it's not clear which parts you used, what you changed, if anything, what is working for you and what is not, etc. Please [edit] your question and post [what you have tried so far](https://meta.stackoverflow.com/q/261592), including example input, expected output, the actual output (if any), and the [**full text** of any errors or tracebacks](https://meta.stackoverflow.com/q/359146), *all as formatted text in the question itself.* Do not post images of text. – MattDMo Dec 23 '21 at 00:46
  • 1
    You can use `.after()` to switch image periodically. – acw1668 Dec 23 '21 at 00:49
  • @acw1668 I have attempted to use .after() , but when I use it in a loop (see edit in question) it just iterates straight from the first to the last and you see nothing inbetween. – Shamus Wood Dec 23 '21 at 01:01
  • You used `.after()` in a wrong way. – acw1668 Dec 23 '21 at 01:04
  • @acw1668 Could you explain how I can achieve this using `.after()` then, I do not have any prior knowledge of such function. – Shamus Wood Dec 23 '21 at 01:05

3 Answers3

1

You need to create a function that gets the image off of the list and displays it, and then uses after to call itself again in a second. Your main program needs to call this exactly once, and then it will run until it runs out of things to do.

Here's a working example that uses a text string for simplicity, but it should be obvious how to modify it to use images.

import tkinter as tk

images = iter(["1.png", "2.png", "3.png", "4.png", "5.png",
               "6.png", "7.png", "8.png", "9.png", "10.png"])

def next_image():
    try:
        image = next(images)
        label.configure(text=image)
        root.after(1000, next_image)
    except StopIteration:
        return

root = tk.Tk()
label = tk.Label(root, width = 40, height=4)
label.pack()

next_image()

root.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
1

You can use .after() to switch image periodically:

from itertools import cycle

...

# use cycle() instead of iter()
Images = cycle([f"{i}.png" for i in range(1, 5)])

...

def next_image():
    # use next() to get next image in the cycle list
    Label1.image = ImageTk.PhotoImage(file=next(Images))
    Label1['image'] = Label1.image
    # switch image again after 1 second
    Label1.after(1000, next_image)

next_image()  # start the loop

Window.mainloop()
acw1668
  • 40,144
  • 5
  • 22
  • 34
0

This worked, Thank you @acw1668 and @Bryan Oakley.

from tkinter import *
from PIL import ImageTk, Image

Window = Tk()
Window.geometry("1920x1080")
Window.resizable(0, 0)

Label1 = Label(Window)
Label1.pack()

Images = iter(["1.png", "2.png", "3.png", "4.png", "5.png", "6.png", 
         "7.png", "8.png", "9.png", "10.png"])

def Next_Image(Val):
    try:
        Image1 = next(Images)
    except StopIteration:
        return

    Image1 = ImageTk.PhotoImage(Image.open("BuyingConfig\\" + Image1))
    Label1.Image = Image1
    Label1["image"] = Image1

    Window.after(3000, lambda:Next_Image(1))

Window.after(0, lambda:Next_Image(1))
Window.mainloop()