The reason why your code doesn't display any images is a bit complicated. There are two factors working together:
- Because you're creating your labels (the ones that you use to display the images) in a loop, you end up creating 3 labels and 3 buttons - one for each image. All of these are arranged below each other, so depending on the size of your images, some of them might be below the window's bottom edge. If you use small images, you'll see three "Next image" buttons in your window.
- Tkinter images are garbage collected if you don't keep a reference to them in your python code. Since your loop overwrites the value of the
img
variable in each iteration, all images except the last one are garbage collected and aren't displayed.
To fix your code, first start by removing that loop. You don't need 3 labels and 3 buttons, and you don't need to load all 3 images immediately when the program starts either.
The code that loads and displays the image should be moved into the next_img
function. You can update the label's image with the command panel['image'] = img
.
In order to cycle through the list of images, it's easiest to use an iterator. You can turn your list of images into an iterator by calling images = iter(images)
. Then you can use the next
function to get the next image from the iterator when you need it.
import tkinter as tk
from PIL import ImageTk, Image
win = tk.Tk()
win.geometry('800x500') # set window size
win.resizable(0, 0) # fix window
panel = tk.Label(win)
panel.pack()
images = ['01.jpg', '02.jpg', '03.jpg']
images = iter(images) # make an iterator
def next_img():
try:
img = next(images) # get the next image from the iterator
except StopIteration:
return # if there are no more images, do nothing
# load the image and display it
img = Image.open(img)
img = ImageTk.PhotoImage(img)
panel.img = img # keep a reference so it's not garbage collected
panel['image'] = img
btn = tk.Button(text='Next image', command=next_img)
btn.pack()
# show the first image
next_img()
win.mainloop()
This code will loop through the images once, and when the last image is reached, pressing the "Next image" button will have no effect. If you want to wrap around to the first image, you can itertools.cycle
to create an infinitely looping iterator instead:
images = itertools.cycle(images)