Как создать быстрое слайд-шоу в python? - PullRequest
0 голосов
/ 01 марта 2020

Я пытался создать слайд-шоу с python до l oop более 5500 изображений быстрее, чем я мог вручную. Я использовал tkinter, и параметр slide_interval должен выполнить эту работу. Слайд-шоу действительно будет длиннее, если я установлю, например, slide_interval = 5000, но без разницы, если я установлю его на 500, 50 или 5, для отображения каждого изображения все равно потребуется примерно то же количество секунд, что и для меня. для каждого изображения будет потрачено 1 или 0,5 секунды.

Вот код:

#!/usr/bin/env python3
"""Display a slideshow from a list of filenames"""

import os
import tkinter

from itertools import cycle
from PIL import Image, ImageTk


class Slideshow(tkinter.Tk):
    """Display a slideshow from a list of filenames"""
    def __init__(self, images, slide_interval):
        """Initialize

        images = a list of filename 
        slide_interval = milliseconds to display image
        """
        tkinter.Tk.__init__(self)
        self.geometry("+0+0")
        self.slide_interval = slide_interval
        self.images = None
        self.set_images(images)
        self.slide = tkinter.Label(self)
        self.slide.pack()

    def set_images(self, images):
         self.images = cycle(images)

    def center(self):
        """Center the slide window on the screen"""
        self.update_idletasks()
        w = self.winfo_screenwidth()
        h = self.winfo_screenheight()
        size = tuple(int(_) for _ in self.geometry().split('+')[0].split('x'))
        x = w / 2 - size[0] / 2
        y = h / 2 - size[1] / 2
        self.geometry("+%d+%d" % (x, y))

    def set_image(self):
        """Setup image to be displayed"""
        self.image_name = next(self.images)
        filename, ext = os.path.splitext(self.image_name)
        self.image = ImageTk.PhotoImage(Image.open(self.image_name))

    def main(self):
        """Display the images"""
        self.set_image()
        self.slide.config(image=self.image)
        self.title(self.image_name)
        self.center()
        self.after(self.slide_interval, self.start)

    def start(self):
        """Start method"""
        self.main()
        self.mainloop()


if __name__ == "__main__":
    slide_interval = 1


    import glob
    images = glob.glob("traralgon/*.jpg")

    # start the slideshow
    slideshow = Slideshow(images, slide_interval)
    slideshow.start()

Ответы [ 2 ]

1 голос
/ 01 марта 2020

Примерно так:

import tkinter as tk


class Application(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title("Slideshow")
        self.geometry("256x256")
        self.resizable(width=False, height=False)
        self.current_slide = tk.Label(self)
        self.current_slide.pack()
        self.duration_ms = 1000

    def set_image_directory(self, path):
        from pathlib import Path
        from PIL import Image, ImageTk
        from itertools import cycle

        image_paths = Path(path).glob("*.jpg")
        self.images = cycle(zip(map(lambda p: p.name, image_paths), map(ImageTk.PhotoImage, map(Image.open, image_paths))))

    def display_next_slide(self):
        name, self.next_image = next(self.images)
        self.current_slide.config(image=self.next_image)
        self.title(name)
        self.after(self.duration_ms, self.display_next_slide)

    def start(self):
        self.display_next_slide()

def main():

    application = Application()
    application.set_image_directory("dir/to/images")
    application.start()
    application.mainloop()


if __name__ == "__main__":
    import sys
    sys.exit(main())

Вам нужно будет спросить себя, хотите ли вы загрузить все изображения заранее, до начала слайд-шоу, и просто сохранить их в памяти (это может занять некоторое время в зависимости от о том, сколько изображений у вас есть), или если вы хотите загружать изображения только тогда, когда они должны отображаться (если интервал между изображениями особенно мал, вы можете заметить, что загрузка следующего изображения замедляет процесс).

1 голос
/ 01 марта 2020

Проблема в том, что вы звоните self.main() и self.mainloop() на каждом интервале. Это вызовет огромные проблемы с производительностью и, вероятно, достигнет sh всего через секунду или две. Вы никогда не должны вызывать mainloop() более одного раза, и нет смысла воссоздавать весь пользовательский интерфейс на каждом l oop.

Вместо этого вам нужно написать функцию, которая получает изображение, а затем настраивает существующий метка, а не воссоздание всего GUI на каждой итерации.

Пример:

def main(self):
    ...
    self.next_image()

def next_image(self):
    self.image_name = next(self.images)
    filename, ext = os.path.splitext(self.image_name)
    self.image = tkinter.PhotoImage(file=self.image_name)
    self.slide.configure(image=self.image)
    self.after(self.slide_interval, self.next_image)
...