如何遍历图像列表并在 Tkinter 中显示它们

Posted

技术标签:

【中文标题】如何遍历图像列表并在 Tkinter 中显示它们【英文标题】:How can I Iterate through a list of Images and Display them in Tkinter 【发布时间】:2022-01-24 02:53:12 【问题描述】:

所以,我的目标是在 Tkinter 中创建一种幻灯片。我有一个图像列表,例如 Images = ["1.png", "2.png", ...],我希望能够遍历列表并在 Tkinter 窗口中显示每个图像,这个概念很简单如下:

显示图像 1 30 秒延迟 显示图像 2 30 秒延迟 显示图像 3

我已经设法使用按钮来迭代图像,但是,我不想点击按钮,因为它是为了模仿幻灯片,我也尝试循环一个函数,但 time.sleep() 函数由于 Tkinter 的行为方式,不会以正确的方式延迟。

我主要使用来自here 的源代码来实现上述目标,如果能帮助实现上述目标,我将不胜感激。

我的代码:

from tkinter import *
from PIL import ImageTk, Image

Window = Tk()
Window.geometry("1920x1080")
Window.resizable(0, 0)

Label1 = Label(Window)
Label1.pack()

Images = iter(["1.png", "2.png", "3.png", "4.png", "5.png", 
         "6.png", "7.png", "8.png", "9.png", "10.png"])

def Next_Image(Val):
    try:
        Image1 = next(Images)
    except StopIteration:
        return

    Image1 = ImageTk.PhotoImage(Image.open(Image1))
    Label1.Image = Image1
    Label1["image"] = Image1

Button1 = Button(text = "Next image", command = 
lambda:Next_Image(1))
Button1.place(x = 50, y = 50)

Next_Image(1)

Window.mainloop()

我也尝试使用.after(),但是它并没有显示每张图片,它会直接从第一张图片跳到最后一张,并带有复合延迟。

for x in range(1, 11):

    Window.after(1000, lambda : Next_Image(1))

【问题讨论】:

寻求调试帮助的问题(“为什么这段代码不起作用?”)应包括所需的行为、特定问题或错误所需的最短代码作为格式化文本(不是图像)在问题本身中。没有明确的问题陈述的问题对其他读者没有用处。请参阅:minimal reproducible example。 @MattDMo 你是说我的问题没有提供足够的上下文,因为我认为它已经很清楚地涵盖了它,我什至包含了我基于另一篇帖子的代码。 您根本没有包含任何代码。你链接到另一个包含一些代码的问题,但不清楚你使用了哪些部分,你改变了什么,如果有的话,什么对你有用,什么不是,等等。请edit你的问题并发布what you have tried so far,包括示例输入、预期输出、实际输出(如果有)和full text of any errors or tracebacks,都在问题本身中作为格式化文本。请勿发布文本图像。 您可以使用.after()定期切换图像。 @acw1668 我曾尝试使用 .after() ,但是当我在循环中使用它时(请参阅有问题的编辑),它只是从第一个直接迭代到最后一个,而你看不到任何中间内容。 【参考方案1】:

这很有效,谢谢@acw1668 和@Bryan Oakley。

from tkinter import *
from PIL import ImageTk, Image

Window = Tk()
Window.geometry("1920x1080")
Window.resizable(0, 0)

Label1 = Label(Window)
Label1.pack()

Images = iter(["1.png", "2.png", "3.png", "4.png", "5.png", "6.png", 
         "7.png", "8.png", "9.png", "10.png"])

def Next_Image(Val):
    try:
        Image1 = next(Images)
    except StopIteration:
        return

    Image1 = ImageTk.PhotoImage(Image.open("BuyingConfig\\" + Image1))
    Label1.Image = Image1
    Label1["image"] = Image1

    Window.after(3000, lambda:Next_Image(1))

Window.after(0, lambda:Next_Image(1))
Window.mainloop()

【讨论】:

【参考方案2】:

您可以使用.after()定期切换图像:

from itertools import cycle

...

# use cycle() instead of iter()
Images = cycle([f"i.png" for i in range(1, 5)])

...

def next_image():
    # use next() to get next image in the cycle list
    Label1.image = ImageTk.PhotoImage(file=next(Images))
    Label1['image'] = Label1.image
    # switch image again after 1 second
    Label1.after(1000, next_image)

next_image()  # start the loop

Window.mainloop()

【讨论】:

【参考方案3】:

您需要创建一个函数,从列表中取出图像并显示它,然后使用after 在一秒钟内再次调用自身。你的主程序需要只调用一次,然后它会一直运行,直到它做完所有事情。

为了简单起见,这是一个使用文本字符串的工作示例,但如何修改它以使用图像应该很明显。

import tkinter as tk

images = iter(["1.png", "2.png", "3.png", "4.png", "5.png",
               "6.png", "7.png", "8.png", "9.png", "10.png"])

def next_image():
    try:
        image = next(images)
        label.configure(text=image)
        root.after(1000, next_image)
    except StopIteration:
        return

root = tk.Tk()
label = tk.Label(root, width = 40, height=4)
label.pack()

next_image()

root.mainloop()

【讨论】:

谢谢!当我看到你的评论时,我真的只是解决了这个问题,但非常感谢!

以上是关于如何遍历图像列表并在 Tkinter 中显示它们的主要内容,如果未能解决你的问题,请参考以下文章

哪个更适合tkinter网格,放置单个项目或循环遍历列表来放置它们?

如何遍历地图列表并在颤动列表视图中显示文本小部件?

获取所有联系人并在列表视图中显示它们

如何更新 Tkinter 标签小部件的图像?

下载图像缩略图并在 ListView C# 中显示它们

在 Firebase 实时数据库中,我如何遍历每个产品并在回收站视图中显示它们的详细信息