python - 如何关闭已经显示的图像并显示另一张图像?

标签 python image tkinter

我正在创建一个软件,当它收到按钮信号时,显示一幅图像,1 秒后显示另一幅图像。问题是我不知道如何关闭图像,一旦它已经全屏显示,假设 Esc 关闭,但它不起作用。

import sys
import RPi.GPIO as GPIO 
import time 

pulse = 16
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

GPIO.setup(pulse, GPIO.IN, GPIO.PUD_UP) 

if sys.version_info[0] == 2:  
    import Tkinter
    tkinter = Tkinter 
else:
    import tkinter
from PIL import Image, ImageTk

blackImage = Image.open("black.png")
pattern = Image.open("pattern.jpg")

def showImage(nimage):
    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.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
    canvas = tkinter.Canvas(root,width=w,height=h)
    canvas.pack()
    canvas.configure(background='black')
    imgWidth, imgHeight = nimage.size
    if imgWidth > w or imgHeight > h:
        ratio = min(w/imgWidth, h/imgHeight)
        imgWidth = int(imgWidth*ratio)
        imgHeight = int(imgHeight*ratio)
        nimage = nimage.resize((imgWidth,imgHeight), Image.ANTIALIAS)
    image = ImageTk.PhotoImage(nimage)
    imagesprite = canvas.create_image(w/2,h/2,image=image)
    root.mainloop()


while True:

    if GPIO.input(pulse) == False:
        time.sleep(0.1)
        print ("Shoot")
        showImage(blackImage)
        time.sleep(1)
        showImage(pattern)

结果是,当按下按钮时,屏幕上将显示黑色图像,然后显示图案图像,但只显示黑色图像,并且当第二个图像没有被图案图像替换时该模式,不会同时关闭。按Esc,我必须按Alt + F4

最佳答案

GUI编程是用户event-driven这意味着它的编程规则与您可能习惯做的非常常见的函数级编程不同。 @stovfl 评论中的链接存在差异,因此我建议您阅读它的内容。

为了帮助理解这如何影响事情的完成方式,下面尝试将您的代码转换为这种范例。另请注意,由于我没有 Raspberry Pi,因此代码还(有条件地)将事件处理程序回调函数绑定(bind)到鼠标左键事件以模拟存在一个事件处理程序回调函数 - 因此,如果您愿意,请随意删除该内容你会的。

我尝试尽可能多地封装需要在单个“应用程序”类中完成的操作,因为这样做可以减少使用一堆代码的需要,从而使编码变得更加干净。全局变量。

from PIL import Image, ImageTk
try:
    import tkinter as tk  # Python 3
except ModuleNotFoundError:
    import Tkinter as tk  # Python 2

try:
    import RPi.GPIO as GPIO
except ModuleNotFoundError:
    GPIO_present = False  # No Raspberry Pi
else:
    GPIO_present = True
    GPIO_PULSE = 16  # Button channel.
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(GPIO_PULSE, GPIO.IN, GPIO.PUD_UP)


class Application(tk.Frame):
    DELAY = 100  # ms

    def __init__(self, master=None):
        super().__init__(master)
        self.pack()
        self.w, self.h = self.winfo_screenwidth(), self.winfo_screenheight() # Fullscreen
        self.create_widgets()
        self.flag = False  # Initialize button clicked flag.
        self.after(self.DELAY, self.check_signal)  # Start background polling.

    def create_widgets(self):
        self.canvas = tk.Canvas(root, width=self.w, height=self.h, background='black')
        self.canvas.pack()

        pil_img = Image.open("black.png")

    def _load_image(self, filename):
        """ Use PIL to load (and resize if necessary) an image. """
        pil_img = Image.open(filename)
        img_width, img_height = pil_img.size

        if img_width > self.w or img_height > self.h:  # Too big?
            ratio = min(self.w/img_width, self.h/img_height)
            img_width, img_height = int(img_width*ratio), int(img_height*ratio)
            pil_img = pil_img.resize((img_width, img_height), Image.ANTIALIAS)  # Resize.

        img = ImageTk.PhotoImage(pil_img)  # Convert to tkinter PhotoImage.
        return img

    def create_widgets(self):
        self.canvas = tk.Canvas(root, width=self.w, height=self.h, background='black')
        self.canvas.pack()

        self.black_img = self._load_image("black.png")
        self.pattern_img = self._load_image("pattern.png")

        # Create a canvas image object place-holder for show_image() to update.
        self.image_id = self.canvas.create_image(self.w/2, self.h/2, image=None)

    def show_image(self, img):
        self.cur_img = img
        self.canvas.itemconfigure(self.image_id, image=self.cur_img)

    def show_next_image(self):
        self.after(100)  # Pause 0.1 second - avoid using time.sleep()
        print("Shoot")
        self.show_image(self.black_img)
        self.after(1000)  # Pause 1 second - avoid using time.sleep()
        self.show_image(self.pattern_img)

    def update_flag(self, e):
        """ Mouse left-button clicked handler. """
        self.flag = True

    def check_signal(self):
        if GPIO_present:
            self.flag = not GPIO.input(GPIO_PULSE)
        else:
            pass  # Assume something else is keeping self.flag updated.

        if self.flag:
            self.show_next_image()
            self.flag = False  # Reset

        root.after(self.DELAY, self.check_signal)  # Check again after delay.

if __name__ == '__main__':

    root = tk.Tk()
    w, h = root.winfo_screenwidth(), root.winfo_screenheight()
    root.overrideredirect(True)
    root.geometry("%dx%d+0+0" % (w, h))  # Fullscreen
    root.focus_set()
    root.bind("<Escape>", lambda e: e.widget.quit())

    app = Application(root)

    if not GPIO_present:
        # Using left mouse-button as substitute for GPIO.
        # Bind left mouse button click event handler.
        root.bind("<Button-1>", app.update_flag)

    app.mainloop()

关于python - 如何关闭已经显示的图像并显示另一张图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54410023/

相关文章:

python - 从 Tkinter 的 Entry 中获取值(value)

python - 使用 Pandas 从 csv 读取到 DataFrame 时转换空值后设置数据类型

Odoo v9.0 中不显示图像

html - 使用@media 属性更改图像的内容 URL

image - 如何根据我的预测获得 ROI 坐标?

python - wordend 不考虑撇号

python - 更新未在 mysql 服务器上提交flask-sqlalchemy

python - couchdbkit:如何批量保存附件

python 列表理解 : return a list of strings instead of a list of lists

python - 包装 Tkinter/ttk 的高级框架