【发布时间】:2021-03-10 13:25:39
【问题描述】:
我使用的是 Raspberry Pi 3B+ (Raspbian),我正在尝试在启动时加载一个 Python 脚本,该脚本将 720p 图像显示为全屏模式,然后用户应该能够按下一个按钮转到下一个图片。
目前,我已经创建了允许图像显示和图像因按钮而改变的代码。
现在我无法将图像加载到全屏模式并在启动时启动。我遵循了许多关于如何在启动时加载 GUI Python 脚本的指南和教程,但它们似乎都不适用于我的特定脚本(但它们在启动时从他们的示例脚本成功加载),这让我觉得有一个代码中关于为什么它无法启动的问题(可能是因为我没有实现它们以全屏打开)。这些是我尝试过的所有指南(https://www.raspberrypi-spy.co.uk/2015/02/how-to-autorun-a-python-script-on-raspberry-pi-boot/、raspberry pi : Auto run GUI on boot、https://raspberrypi.stackexchange.com/questions/4123/running-a-python-script-at-startup、https://www.digikey.ca/en/maker/blogs/2018/how-to-run-python-programs-on-a-raspberry-pi、https://www.instructables.com/Raspberry-Pi-Launch-Python-script-on-startup/、https://bc-robotics.com/tutorials/running-python-program-boot-raspberry-pi/),我想重点介绍本教程中的 GUI 方法。问题(https://learn.sparkfun.com/tutorials/how-to-run-a-raspberry-pi-program-on-startup/all)
在 GUI 编程方面,我现在是个初学者(我从网上获取了原始脚本并对其进行了修改以包含按钮),但我不太确定如何实现全屏选项到显示图像的代码中。
这是我目前拥有的(将图像加载到窗口中,然后您可以使用按钮更改为下一个图像)。在我的代码开头,我尝试从后面列出的示例中添加一些函数,这些函数允许切换全屏以及它们在底部的相关根函数以补充这一点
import tkinter as tk
from PIL import Image, ImageTk
import time
import sys
import os
import keyboard
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(10, GPIO.FALLING)
def toggle_fullscreen(event=None): # I added this in to try full screen
global root
global fullscreen
# Toggle between fullscreen and windowed modes
fullscreen = not fullscreen
root.attributes('-fullscreen', fullscreen)
resize()
# Return to windowed mode
def end_fullscreen(event=None): # I added this in to try full screen
global root
global fullscreen
# Turn off fullscreen mode
fullscreen = False
root.attributes('-fullscreen', False)
root= tk.Tk() # I added this in to try full screen
class HiddenRoot(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
#hackish way, essentially makes root window
#as small as possible but still "focused"
#enabling us to use the binding on <esc>
self.wm_geometry("0x0+0+0")
self.window = MySlideShow(self)
#self.window.changeImage()
self.window.startSlideShow()
class MySlideShow(tk.Toplevel):
def __init__(self, *args, **kwargs):
tk.Toplevel.__init__(self, *args, **kwargs)
#remove window decorations
self.overrideredirect(True)
#save reference to photo so that garbage collection
#does not clear image variable in show_image()
self.persistent_image = None
self.imageList = []
self.pixNum = 0
#used to display as background image
self.label = tk.Label(self)
self.label.pack(side="top", fill="both", expand=True)
self.getImages()
#### Added the GPIO event here
GPIO.add_event_callback(10, self.changeImage)
def getImages(self):
'''
Get image directory from command line or use current directory
'''
if len(sys.argv) == 2:
curr_dir = sys.argv[1]
else:
curr_dir = '.'
for root, dirs, files in os.walk(curr_dir):
for f in files:
if f.endswith(".png") or f.endswith(".jpg"):
img_path = os.path.join(root, f)
print(img_path)
self.imageList.append(img_path)
def startSlideShow(self, delay=4):
myimage = self.imageList[self.pixNum]
self.pixNum = (self.pixNum + 1) % len(self.imageList)
self.showImage(myimage)
#self.after(delay*1000, self.startSlideShow)
# while True:
# buttonState = GPIO.input(buttonPin)
# if buttonState == False:
# self.startSlideShow(self, delay=4)
#@staticmethod
def changeImage(self, pull_up_down=GPIO.PUD_DOWN):
prev_input = 0
while True:
#take a reading
input = GPIO.input(10)
#if the last reading was low and this one high, print
if ((not prev_input) and input):
myimage = self.imageList[self.pixNum]
self.pixNum = (self.pixNum + 1) % len(self.imageList)
self.showImage(myimage)
#update previous input
prev_input = input
#slight pause to debounce
time.sleep(0.05)
# myimage = self.imageList[self.pixNum]
# self.pixNum = (self.pixNum + 1) % len(self.imageList)
# self.showImage(myimage)
def showImage(self, filename):
image = Image.open(filename)
img_w, img_h = image.size
scr_w, scr_h = self.winfo_screenwidth(), self.winfo_screenheight()
width, height = min(scr_w, img_w), min(scr_h, img_h)
image.thumbnail((width, height), Image.ANTIALIAS)
#set window size after scaling the original image up/down to fit screen
#removes the border on the image
scaled_w, scaled_h = image.size
self.wm_geometry("{}x{}+{}+{}".format(scaled_w,scaled_h,0,0))
# create new image
self.persistent_image = ImageTk.PhotoImage(image)
self.label.configure(image=self.persistent_image)
slideShow = HiddenRoot()
slideShow.bind("<Escape>", lambda e: slideShow.destroy()) # exit on esc
slideShow.mainloop()
root.bind('<F11>', toggle_fullscreen) # I added this in to try full screen
root.bind('<Escape>', end_fullscreen) # I added this in to try full screen
toggle_fullscreen() # I added this in to try full screen
root.mainloop() # I added this in to try full screen
GPIO.cleanup()
从我之前说过要注意的那个指南中,这里是他们将时钟加载到全屏模式的代码(我遵循他们在启动时加载脚本的方法)
import tkinter as tk
import tkinter.font as tkFont
import time
###############################################################################
# Parameters and global variables
# Default font size
font_size = -24
# Declare global variables
root = None
dfont = None
frame = None
dtime = None
# Global variable to remember if we are fullscreen or windowed
fullscreen = False
###############################################################################
# Functions
# Toggle fullscreen
def toggle_fullscreen(event=None):
global root
global fullscreen
# Toggle between fullscreen and windowed modes
fullscreen = not fullscreen
root.attributes('-fullscreen', fullscreen)
resize()
# Return to windowed mode
def end_fullscreen(event=None):
global root
global fullscreen
# Turn off fullscreen mode
fullscreen = False
root.attributes('-fullscreen', False)
resize()
# Automatically resize font size based on window size
def resize(event=None):
global time_dfont
global button_dfont
global frame
# Resize font based on frame height (minimum size of 12)
# Use negative number for "pixels" instead of "points"
new_size = -max(12, int((frame.winfo_height() / 2)))
time_dfont.configure(size=new_size)
new_size = -max(12, int((frame.winfo_height() / 30)))
button_dfont.configure(size=new_size)
# Read values from the sensors at regular intervals
def update():
global root
global dtime
# Get local time
local_time = time.localtime()
# Convert time to 12 hour clock
hours = local_time.tm_hour
if hours > 12:
hours -= 12
# Add leading 0s
shours = str(hours)
smin = str(local_time.tm_min)
if hours < 10:
shours = '0' + shours
if local_time.tm_min < 10:
smin = '0' + smin
# Construct string out of time
dtime.set(shours + ':' + smin)
# Schedule the poll() function for another 500 ms from now
root.after(500, update)
###############################################################################
# Main script
# Create the main window
root = tk.Tk()
root.title("My Clock")
# Create the main container
frame = tk.Frame(root, bg='black')
# Lay out the main container (expand to fit window)
frame.pack(fill=tk.BOTH, expand=1)
# Variables for holding temperature and light data
dtime = tk.StringVar()
# Create dynamic font for text
time_dfont = tkFont.Font(family='Courier New', size=font_size)
button_dfont = tkFont.Font(size=font_size)
# Create widgets
label_time = tk.Label( frame,
textvariable=dtime,
font=time_dfont,
fg='red',
bg='black')
button_quit = tk.Button(frame,
text="Quit",
font=button_dfont,
command=root.destroy,
borderwidth=0,
highlightthickness=0,
fg='gray10',
bg='black')
# Lay out widgets in a grid in the frame
label_time.grid(row=0, column=0, padx=20, pady=20)
button_quit.grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
# Make it so that the grid cells expand out to fill window
frame.rowconfigure(0, weight=10)
frame.rowconfigure(1, weight=1)
frame.columnconfigure(0, weight=1)
# Bind F11 to toggle fullscreen and ESC to end fullscreen
root.bind('<F11>', toggle_fullscreen)
root.bind('<Escape>', end_fullscreen)
# Have the resize() function be called every time the window is resized
root.bind('<Configure>', resize)
# Schedule the poll() function to be called periodically
root.after(20, update)
# Start in fullscreen mode and run
toggle_fullscreen()
root.mainloop()
现在我想弄清楚的是如何在我的程序中实现他们进入全屏显示的方法
谢谢你:)!
【问题讨论】:
标签: python user-interface tkinter raspberry-pi