Python:使用PIL/TkInter自动幻灯片放映,无需保存图像

2024-06-13 23:26:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在设计一个没有用户干预的幻灯片,其中:

a。每个图像都是由Python脚本本身生成的

b。出于性能原因,不保存文件

c。每幅图像都会在一定时间内全屏显示

d。这是一个永远不会结束的循环。总是会有一个图像显示出来

到目前为止,通过修改在几页中找到的代码,我已经让它运行了。但是每个图像都会显示X时间,然后桌面背景会显示一秒钟左右

我希望从一个文件顺利切换到下一个文件,就像FEH那样。事实上,我正在尝试替换FEH,因为我需要更好地控制每个文件的显示(例如,更改它在屏幕上的显示时间)

这是我的代码:

from PIL import Image 
from PIL import ImageFont
from PIL import ImageDraw
from PIL import ImageTk
import tkinter

def show_center(pil_image, msDelay):
    root = tkinter.Tk()
    w, h = root.winfo_screenwidth(), root.winfo_screenheight()
    root.overrideredirect(1)
    root.geometry("%dx%d+0+0" % (w, h))
    root.focus_set()
    root.attributes("-topmost", True)
    canvas = tkinter.Canvas(root, width=w, height=h, highlightthickness=0)
    canvas.pack()
    canvas.configure(background='black')
    
    image = ImageTk.PhotoImage(pil_image)
    imagesprite = canvas.create_image(w / 2, h / 2, image=image)
    
    root.after(msDelay, root.destroy)
    
    root.mainloop()



### script body

while True:

    # loads common background image
    img = Image.open(baseImage)    
    draw = ImageDraw.Draw(img)
    
    # here: image customization
    draw.rectangle(....)
    draw.text(....)
    img.paste(....)
    
    # shows this file
    thisDelay = some Number Calculation
    show_center(img, thisDelay)

如何避免桌面出现在图像之间?这将运行在一个无头覆盆子。我在Raspbian上使用Python3

提前谢谢


Tags: 文件代码from图像imageimportimgpil
2条回答

嗯,它运行得很好

这个解决方案需要一点逻辑(也许不破坏每个图像的对象是有意义的)和一点好的旧的尝试&;错误

这些变化是:

  • 只初始化画布一次,使用全局变量使其持久化
  • 对于每个图像,调用display函数并继续调用root.update(),直到达到所需的超时

因此,Previor函数被分割,它看起来像:

global canvas, root
global w, h

    def init_image():
    
    global canvas, root
    global w, h 
        
    root = tkinter.Tk()
    w, h = root.winfo_screenwidth(), root.winfo_screenheight()
    root.overrideredirect(1)
    root.geometry("%dx%d+0+0" % (w, h))
    root.focus_set()
    root.attributes("-topmost", True)
    canvas = tkinter.Canvas(root, width=w, height=h, highlightthickness=0)
    canvas.pack()
    canvas.configure(background='black')
    return


def show_center(pil_image, msDelay):

    global canvas, root
    global w, h
    
    image = ImageTk.PhotoImage(pil_image)
    imagesprite = canvas.create_image(w / 2, h / 2, image=image)
    
    inicio = int(time.time() * 1000)
    
    while 1:
        root.update()
        if (int(time.time() * 1000) - inicio) > msDelay:
            break
    return

函数init_image()在开始时调用一次,函数show_center()作为原始post为每个图像调用

我希望这对任何试图实现同样目标的人都有用

您可以使用after()而不是while循环,只需使用Label而不是Canvas

import tkinter as tk
from PIL import Image, ImageTk, ImageDraw, ImageFont
import time
import random

def update_image():
    # sample drawing
    image = base_image.copy()
    draw = ImageDraw.Draw(image)
    draw.rectangle((100, 100, 500, 400), outline=random.choice(('red', 'green', 'blue', 'magenta', 'gold', 'orange')))
    draw.text((120, 120), f"""{time.strftime("%F %T")}""")

    # update image
    tkimg = ImageTk.PhotoImage(image)
    label.config(image=tkimg)
    label.image = tkimg # save a reference to avoid garbage collected

    ms_delay = random.randint(1000, 9000) # sample delay calculation
    root.after(ms_delay, update_image)

root = tk.Tk()
root.attributes("-fullscreen", 1, "-topmost", 1)

base_image = Image.open("/path/to/base/image")

# label for showing image
label = tk.Label(root, bg="black")
label.pack(fill="both", expand=1)

update_image() # start the slide show
root.mainloop()

相关问题 更多 >