How do I get my tkinter picture viewer working?
Question: I've been trying to teach myself tkinter and wanted to make a program that
would find all the pictures in the directory and sub-directories of a folder
and then display them one by one with a button to either save the file into
the "Yes", "Maybe", or "Skip" folders or simply delete the file.

Here's what I'm trying to get it to look like: [![enter image description
here](http://i.stack.imgur.com/EOaqL.png)](http://i.stack.imgur.com/EOaqL.png)

And here is my code which tries to do just that:

    
    
    # Python 3.4
    
    import os
    import tkinter as tk
    from tkinter import Frame, Button
    from PIL import Image, ImageTk
    from send2trash import send2trash
    
    tk_root = tk.Tk()
    tk_root.title("Picture Viewer - Do I want to keep this picture?")
    file_count = 0
    
    p = path = 'C:\\Users\\MyUserName\\Desktop\\Test\\'
    yes = lambda img: os.rename(img, p+'Yes\\Picture_{0}.jpg'.format(file_count))
    maybe = lambda img: os.rename(img, p+'Maybe\\Picture_{0}.jpg'.format(file_count))
    skip = lambda img: os.rename(img, p+'Skipped\\Picture_{0}.jpg'.format(file_count)) 
    delete = lambda img: send2trash(img) # Note: os.remove('img.jpg') also works
    
    def search(directory):
        global file_count
        for root, subdirs, files in os.walk(directory):
            for file in files:
                if os.path.splitext(file)[1].lower() in ('.jpg', '.jpeg'):
                    img = os.path.join(root, file)
                    file_count += 1
    
                    top_frame = Frame(tk_root)
                    bottom_frame = Frame(tk_root)
                    top_frame.pack(side='top')
                    bottom_frame.pack(side='bottom')
    
                    picture = ImageTk.PhotoImage(Image.open(img))
                    picture = tk.Label(tk_root, image=picture)
                    picture.pack(side='top')
    
                    button_yes = Button(top_frame, text="Yes", command=lambda x=img:yes(x))
                    button_maybe = Button(top_frame, text="Maybe", command=lambda x=img:maybe(x))
                    button_skip = Button(top_frame, text="skip", command=lambda x=img:skip(x))
                    button_delete = Button(bottom_frame, text="Delete", command=lambda x=img:delete(x))
    
                    button_yes.pack(side='left')
                    button_maybe.pack(side='left')
                    button_skip.pack(side='left')
                    button_delete.pack(side='bottom')
        print('All done!')
    search('Test')
    

However, the problem is after I launch the program it isn't working well at
all. It simply moves the first picture, "1.jpg", into whatever folder I pick
(or delete) and then giving the following error if I try to sort another
image:

> FileNotFoundError: [WinError 2] The system cannot find the file specified:
> 'Test\Example.jpg' -> 'C:\Users\Vale\Desktop\Test\Maybe\1.jpg'

Perhaps most importantly the images are not displaying and cycling properly.
It is just a gray box in the middle each time. How do I get my program to
work? I'm aware I need to get the image to appear still and something needs to
be done to get the program to move onto the next picture as well (so I don't
get FileNotFoundError for trying to sort the same picture twice), but I'm
unsure what to do differently after watching tutorials and reading
documentation.


Answer: As mentioned by BlackJack, your code creates the GUI Widgets over and over.
You'll need to move that out from the loop. Also for displaying the image in
the `Label`, you can't use `picture` as the name for both the `ImageTk` object
and `Label` object.

Suggestions to changes. You could use a Generator to get the image
path/filename. And make regular functions instead of using lambda. I had an
interest in seeing how it could work, so I made the program below based on
your code. When I tested it I had different paths, working on OSX, so haven't
tested it with your Windows paths (that I put into the code here).

    
    
    import os
    import tkinter as tk
    from tkinter import Frame, Button
    from PIL import Image, ImageTk
    
    tk_root = tk.Tk()
    tk_root.title("Picture Viewer - Do I want to keep this picture?")
    file_count = 0
    
    p = path = 'C:\\Users\\MyUserName\\Desktop\\Test\\'
    
    
    def search(directory):
        global file_count
        for root, subdirs, files in os.walk(directory):
            for file in files:
                if os.path.splitext(file)[1].lower() in ('.jpg', '.jpeg'):
                    img = os.path.join(root, file)
                    file_count += 1
                    yield img
    
    
    def next_image():
        try:
            global photo_path
            photo_path = next(path_generator)
            photo = ImageTk.PhotoImage(Image.open(photo_path))
            picture.configure(image=photo)
            picture.image = photo
        except StopIteration:
            picture.configure(image='', text='All done!')
    
    
    def move_file(directory):
        if not os.path.exists(directory):
            os.makedirs(directory)
        new_file = directory + 'Picture_{0}.jpg'.format(file_count)
        os.rename(photo_path, new_file)
    
    
    def yes():
        move_file(path + 'Yes\\')
        next_image()
    
    
    def maybe():
        move_file(path + 'Maybe\\')
        next_image()
    
    
    def skip():
        move_file(path + 'Skipped\\')
        next_image()
    
    
    def delete():
        # Code for deleting file here
        next_image()
    
    top_frame = Frame(tk_root)
    bottom_frame = Frame(tk_root)
    top_frame.pack(side='top')
    bottom_frame.pack(side='bottom')
    
    path_generator = search(p)
    photo_path = next(path_generator)
    
    photo = ImageTk.PhotoImage(Image.open(photo_path))
    picture = tk.Label(tk_root, image=photo)
    picture.image = photo
    picture.pack(side='top')
    
    button_yes = Button(top_frame, text="Yes", command=yes)
    button_maybe = Button(top_frame, text="Maybe", command=maybe)
    button_skip = Button(top_frame, text="skip", command=skip)
    button_delete = Button(bottom_frame, text="Delete", command=delete)
    
    button_yes.pack(side='left')
    button_maybe.pack(side='left')
    button_skip.pack(side='left')
    button_delete.pack(side='bottom')
    
    tk_root.mainloop()
    

**EDIT:**

One issue with this code seems to be that it runs through the subdirectories
(Yes, Maybe, Skipped). So you'll be presented with the images twice if it is
in the path and then moved.

If you don't want to traverse the Yes, Maybe and Skipped folders, you can
change the `search` function to:

    
    
    def search(directory):
        global file_count
        excludes = ['Yes', 'Maybe', 'Skipped']
        for root, subdirs, files in os.walk(directory, topdown=True):
            subdirs[:] = [d for d in subdirs if d not in excludes]
            for file in files:
                if os.path.splitext(file)[1].lower() in ('.jpg', '.jpeg'):
                    img = os.path.join(root, file)
                    file_count += 1
                    yield img
    

