GUI-программирование - это пользователь управляемый событиями , что означает, что правила для программирования отличаются от очень распространенного программирования на функциональном уровне, к которому вы, вероятно, привыкли.Ссылка в комментарии @ 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()