1

I'm writing a slideshow program with Tkinter, but I don't know how to go to the next image without binding a key.

import os, sys
import Tkinter
import Image, ImageTk
import time

root = Tkinter.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (w, h))
root.focus_set()

root.bind("<Escape>", lambda e: e.widget.quit())

image_path = os.path.join(os.getcwd(), 'images/')
dirlist = os.listdir(image_path)

for f in dirlist:
    try:
        image = Image.open(image_path+f)
        tkpi = ImageTk.PhotoImage(image)        
        label_image = Tkinter.Label(root, image=tkpi) # ?
        label_image.place(x=0,y=0,width=w,height=h)
        root.mainloop(0)
    except IOError:
        pass
root.destroy()

I would like to add a time.sleep(10) "instead" of the root.mainloop(0) so that it would go to the next image after 10s. Now it changes when I press ESC. How can I have a timer there?

edit: I should add that I don't want another thread that does a sleep even though it works.

2

2 Answers 2

5

You can try

root.after(10*1000, root.quit)
Sign up to request clarification or add additional context in comments.

Comments

5

There's no need to do a loop over your images -- you're already running in a loop (mainloop) so take advantage of it. The typical way to do this is to create a method that draws something, waits for a period of time, then calls itself. This isn't recursion, it's just telling the main loop "after N seconds, call me again".

Here's a working example:

import glob
import Tkinter

class Slideshow:
    def __init__(self, pattern="*.gif", delay=10000):

        root = Tkinter.Tk()
        root.geometry("200x200")

        # this label will be used to display the image. Make
        # it automatically fill the whole window
        label = Tkinter.Label(root) 
        label.pack(side="top", fill="both", expand=True)

        self.current_image = None
        self.image_label = label
        self.root = root
        self.image_files = glob.glob(pattern)
        self.delay = delay # milliseconds

        # schedule the first image to appear as soon after the 
        # the loop starts as possible.
        root.after(1, self.showImage)
        root.mainloop()


    def showImage(self):
        # display the next file
        file = self.image_files.pop(0)
        self.current_image = Tkinter.PhotoImage(file=file)
        self.image_label.configure(image=self.current_image)

        # either reschedule to display the file, 
        # or quit if there are no more files to display
        if len(self.image_files) > 0:
            self.root.after(self.delay, self.showImage)
        else:
            self.root.after(self.delay, self.root.quit)

    def quit(self):
        self.root.quit()


if __name__ == "__main__":
    app=Slideshow("images/*.gif", 1000)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.