如何关闭已经显示的图像并显示另一个?

时间:2019-01-28 20:44:12

标签: 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

1 个答案:

答案 0 :(得分:0)

GUI编程是用户event-driven,这意味着对其编程的规则与您可能习惯于执行的非常常见的函数级编程不同。 @stovfl的评论中的链接涉及到这些差异,因此我建议您阅读其内容。

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

我尝试将尽可能多的需要封装的内容封装在一个“应用程序” class中,因为这样做可以减少使用大量全局变量的需要,从而使编码更加简洁

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()