Reputation: 429
How to use python Tkinter to iterate images?
import tkinter as tk
from PIL import ImageTk, Image
win = tk.Tk()
win.geometry('800x500') # set window size
win.resizable(0, 0) # fix window
images = ['01.jpg', '02.jpg', '03.jpg']
def next_img():
# show next image
for img in images:
img = Image.open(img)
img = ImageTk.PhotoImage(img)
panel = tk.Label(win, image=img)
panel.pack()
btn = tk.Button(text='Next image', command=next_img)
btn.pack()
win.mainloop()
But my panel doesn't show any images. I hope the panel waits me and I click the button to show next images. How to solve it.
Upvotes: 1
Views: 4316
Reputation: 43136
The reason why your code doesn't display any images is a bit complicated. There are two factors working together:
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)
Upvotes: 8
Reputation: 11
Unfortunately, Tkinter is a little confusing and when placing an image in a label or button you will want to add on the line beneath
panel.photo = img
I'm not exactly sure why this works but it seems there are 2 values that take the image to display it.
Upvotes: 1