TKinter Update Image list

Viewed 1075

I am using TKinter to display some images of a folder. Those are loaded from a list:

image_list = [os.path.join("/home/pi/fotos/previews",fn) for fn in next(os.walk("/home/pi/fotos/previews"))[2]]

But the folder is beeing updated with new photos from time to time, so TKinter has to be refreshed somehow, to show those new images as well.

How could I refresh TKinter with a new image list?

Here's the full code:

#!/usr/bin/python

import Image
import ImageTk
import Tkinter
import glob
import sys
import os.path
import os

image_list = [os.path.join("/home/pi/fotos/previews",fn) for fn in next(os.walk("/home/pi/fotos/previews"))[2]]
sorted_imagelist = sorted(image_list, key=str.swapcase, reverse=True)

current = 0

def move(delta):
    global current, sorted_imagelist
    if not (0 <= current - delta < len(sorted_imagelist)):
        tkMessageBox.showinfo('End', 'No more image.')
        return
    current -= delta
    image = Image.open(sorted_imagelist[current])
    photo = ImageTk.PhotoImage(image)
    label['image'] = photo
    label.photo = photo


root = Tkinter.Tk()

root.configure(background="#eee")

label = Tkinter.Label(root, compound=Tkinter.TOP, bg="#eee")
label.pack()
label.place(x=90, y=30)

frame = Tkinter.Frame(root, bg="#eee")
frame.pack()

Tkinter.Button(frame, text='Refresh', height=10, width=25, command=root.update).pack(side=Tkinter.LEFT)
Tkinter.Button(frame, text='Previous picture', height=10, width=25, command=lambda: move(-1)).pack(side=Tkinter.LEFT)
Tkinter.Button(frame, text='Next picture', height=10, width=25, command=lambda: move(+1)).pack(side=Tkinter.LEFT)
Tkinter.Button(frame, text='Quit', height=10, width=25, command=root.quit).pack(side=Tkinter.LEFT)

move(0)

root.attributes('-fullscreen', True)
root.mainloop()

Thanks for help!

2 Answers

I found a solution and will answer my own question to help others:

Actually I created a function that will simply check the list again.

    def refresh(delta):

        global current, sorted_imagelist

        text_list = next(os.walk("/home/pi/fotos/previews"))[2]
        image_list = [os.path.join("/home/pi/fotos/previews",fn) for fn in next(os.walk("/home/pi/fotos/previews"))[2]]

        sorted_textlist = sorted(text_list, key=str.swapcase, reverse=True)
        sorted_imagelist = sorted(image_list, key=str.swapcase, reverse=True)


        print (sorted_imagelist)
        print ('Refreshed')

This function is called every second, so everything works fast.

    def updater():
      threading.Timer(1.0, updater).start()
      refresh(0)

    updater()   

Only problem I am having so far is, that when the current viewed image is the last one of the old list, the 'new' last photo is not being loaded correctly into TKinter. I have to navigate back to the previous and I'm then able to move forward to see the new one.

I am working on a solution to solve that last one.

If you store the list of filenames at time A and then later get the new list of filenames at time B then you can use the set operation symmetric_difference to find the items in B that are not in A (i.e: new files). The Tk after method can let you schedule a function to do this at intervals. You can then create the new Tk images for the new files and add those to your list of Tk images.

Each platform has some API for requesting your application be notified when changes occur to the filesystem. On Windows that's the FindFirstChangeNotification function and its friends or inotify on Linux. However, the simplest cross-platform method is to poll the contents of the directory on a timer.

Related