PySimpleGUI:如何处理持久的用户输入?
PySimpleGUI: How to process persistent user inputs?
我创建了一个简单的 GUI 来控制两个伺服系统。如果用户只有一个输入,GUI 工作正常,但是,它无法处理持久的用户输入。我查看了用于持久用户输入的 PysimpleGUI 说明书演示,但是,我似乎无法在我的代码中实现相同类型的解决方案(Link:https://pysimplegui.readthedocs.io/en/latest/cookbook/#recipe-pattern-2a-persistent-window-multiple-reads-using-an-event-loop)。我在下面附上了我的所有代码:
# -*- coding=utf-8 -*-
import PySimpleGUI as psg
import os
import RPi.GPIO as GPIO
import time
servoPIN_1 = 17 # Declare GPIO pins for servo signal input
servoPIN_2 = 27
GPIO.setmode(GPIO.BCM) # Declare pin numbering system
GPIO.setup(servoPIN_1, GPIO.OUT)
GPIO.setup(servoPIN_2, GPIO.OUT)
PWM_1 = GPIO.PWM(servoPIN_1, 50) # Create PWM channels w/frequency allocation of 50Hz
PWM_2 = GPIO.PWM(servoPIN_2, 50)
psg.theme('DarkAmber') # Add a touch of color
Top_Def = [[psg.Text("Concept 2: Band Pincher", size=(25,1), font=("Courier", 20))], [psg.HorizontalSeparator()]]
LHS_PreDef = [
[psg.Text("Choose pre-selected routine", font=("Courier", 12))],
[psg.Image('/home/pi/Desktop/Motor-Control_Script/image1.png', size=(301,232)),
psg.Button('Delayed Extension Grip', font=("Courier", 10))],
[psg.Image('/home/pi/Desktop/Motor-Control_Script/image2.png', size=(301,99)),
psg.Button('Simultaneous Extension Grip', font=("Courier", 10))],
[psg.Button('hidden', size=(6,2), button_color=(psg.theme_background_color(),psg.theme_background_color()), border_width=0)]
]
RHS_CustomDef = [
[psg.Text("Create custom servo routine", font=("Courier", 12))],
[psg.Image('/home/pi/Desktop/Motor-Control_Script/image3.png', size=(200,200)),
psg.In(size=(20,1), enable_events=True, key= "_Servo1_"), psg.Button('Actuate servo 1', size=(6,2), font=("Courier", 10))],
[psg.Image('/home/pi/Desktop/Motor-Control_Script/image3.png', size=(200,200)),
psg.In(size=(20,1), enable_events=True, key= "_Servo2_"), psg.Button('Actuate servo 2', size=(6,2), font=("Courier", 10))],
[psg.Button('Exit', size=(6,2), font=("Courier", 10))]
]
Layout = [
[Top_Def,psg.Column(LHS_PreDef),psg.VSeparator(), psg.Column(RHS_CustomDef)]
]
window = psg.Window('Handling solutions', Layout)
while True:
event, values = window.read()
if event == psg.WINDOW_CLOSED or event == 'Exit': # if user closes window or clicks cancel
break
elif event == 'Delayed Extension Grip':
PWM_1.start(9)
PWM_2.start(10)
time.sleep(0.5)
PWM_1.ChangeDutyCycle(6)
time.sleep(1.5) # Sets arbitrary sleep time
PWM_2.ChangeDutyCycle(12)
time.sleep(1.5) # can create user input here to confirm parcel placement
PWM_1.ChangeDutyCycle(8) # Simultaneously enclosed parcel
PWM_2.ChangeDutyCycle(10)
time.sleep(0.05)
PWM_1.stop()
PWM_2.stop()
GPIO.cleanup()
elif event == 'Simultaneous Extension Grip':
PWM_1.start(9)
PWM_2.start(10)
time.sleep(0.5)
PWM_1.ChangeDutyCycle(6)
PWM_2.ChangeDutyCycle(11)
time.sleep(1.5) # can create user input here to confirm parcel placement
PWM_1.ChangeDutyCycle(8) # Simultaneously enclosed parcel
PWM_2.ChangeDutyCycle(10)
time.sleep(0.05)
PWM_1.stop()
PWM_2.stop()
GPIO.cleanup()
elif event == 'Actuate servo 1':
PWM_1.start(0)
PWM_1.ChangeDutyCycle(float(values["_Servo1_"]))
time.sleep(0.05)
PWM_1.stop()
y = values["_Servo1_"]
print(y)
PWM_1.ChangeDutyCycle(float(y))
time.sleep(0.05)
PWM_1.stop()
elif event == 'Actuate servo 2':
PWM_2.start(0)
PWM_2.ChangeDutyCycle(float(values["_Servo2_"]))
time.sleep(0.05)
PWM_2.stop()
window.close()
运行 脚本生成此 GUI image
例如:GUI 接受处理的 Actuate Servo 1 的单个输入。但是,不会处理同一字段中的任何后续输入。我不是很熟悉这个包,所以任何帮助将不胜感激。
它看起来工作正常,但不确定您的 GPIO 命令是否有问题。
布局格式有问题。它应该是元素列表的列表,或者行列表和行是元素列表。
...
Top_Def = [[psg.Text("Concept 2: Band Pincher", size=(25,1), font=("Courier", 20))], [psg.HorizontalSeparator()]]
...
Layout = [[Top_Def,psg.Column(LHS_PreDef),psg.VSeparator(), psg.Column(RHS_CustomDef)]]
...
最好运行你在另一个线程中执行GPIO命令,示例代码如下,这里没有任何测试。
# -*- coding=utf-8 -*-
import threading
from time import sleep
import RPi.GPIO as GPIO
import PySimpleGUI as psg
"""
func = {
("GPIO", "cleanup") : GPIO.cleanp,
("PWM", 1, "start") : PWM1.start,
("PWM", 2, "start") : PWM2.start,
("PWM", 1, "stop") : PWM1.stop,
("PWM", 2, "stop") : PWM2.stop,
("PWM", 1, "DutyCycle") : PWM_1.ChangeDutyCycle,
("PWM", 2, "DutyCycle") : PWM_2.ChangeDutyCycle,
"SLEEP" : sleep,
}
def gpib(window, commands):
result = True
for command in commands:
try:
if command[0] == "PWM":
if len(command) == 4:
func[command[:3]](command[3])
elif len(command) == 3:
func[command[:3]]()
elif command[0] == "SLEEP":
func[command[0]](command[1])
elif command[0] == "GPIO":
func[command[:2]]()
except:
result = False
break
window.write_event_value('-THREAD-', result)
command1 = [("PWM", 1, "start", 9), ("PWM", 2, "start", 10), ("SLEEP", 0.5),
("PWM", 1, "DutyCycle", 6), ("SLEEP", 1.5), ("PWM", 1, "DutyCycle", 12),
("SLEEP", 1.5), ("PWM", 1, "DutyCycle", 8), ("PWM", 2, "DutyCycle", 10),
("SLEEP", 0.05), ("PWM", 1, "stop"), ("PWM", 2, "stop"), ("GPIO", "cleanup")]
"""
font10 = ("Courier", 10)
font12 = ("Courier", 12)
font20 = ("Courier", 20)
psg.theme('DarkAmber') # Add a touch of color
psg.set_options(font=font10)
LHS_PreDef = [
[psg.Text("Choose pre-selected routine", font=font12)],
[psg.Image(data=psg.EMOJI_BASE64_HAPPY_HEARTS),
psg.Button('Delayed Extension Grip')],
[psg.Image(data=psg.EMOJI_BASE64_HAPPY_IDEA),
psg.Button('Simultaneous Extension Grip')],
]
RHS_CustomDef = [
[psg.Text("Create custom servo routine", font=("Courier", 12))],
[psg.Image(data=psg.EMOJI_BASE64_HAPPY_CONTENT),
psg.In(size=(20,1), enable_events=True, key= "_Servo1_"),
psg.Button('Actuate servo 1', size=(15,1))],
[psg.Image(data=psg.EMOJI_BASE64_HAPPY_GASP),
psg.In(size=(20,1), enable_events=True, key= "_Servo2_"),
psg.Button('Actuate servo 2', size=(15,1))],
]
Layout = [
[psg.Column([[psg.Text("Concept 2: Band Pincher", font=font20)]], element_justification='left', expand_x=True),
psg.Column([[psg.Button('Exit', size=(6,2))]], element_justification='right', expand_x=True)],
[psg.HorizontalSeparator()],
[psg.Column(LHS_PreDef), psg.VSeparator(), psg.Column(RHS_CustomDef)],
[psg.Button('hidden', size=(6,2), border_width=0, button_color=
(psg.theme_background_color(), psg.theme_background_color()))],
]
window = psg.Window('Handling solutions', Layout)
while True:
event, values = window.read()
if event in (psg.WINDOW_CLOSED, 'Exit'):
break
elif event == 'Delayed Extension Grip':
print(event)
# threading.Thread(target=gpib, args=(window, command1), daemon=True).start()
elif event == 'Simultaneous Extension Grip':
print(event)
elif event == 'Actuate servo 1':
print(event, values["_Servo1_"])
elif event == 'Actuate servo 2':
print(event, values["_Servo2_"])
elif event == '-THREAD-':
print(event, f'GPIO command {"OK" if values[event] else "NG"}')
window.close()
我创建了一个简单的 GUI 来控制两个伺服系统。如果用户只有一个输入,GUI 工作正常,但是,它无法处理持久的用户输入。我查看了用于持久用户输入的 PysimpleGUI 说明书演示,但是,我似乎无法在我的代码中实现相同类型的解决方案(Link:https://pysimplegui.readthedocs.io/en/latest/cookbook/#recipe-pattern-2a-persistent-window-multiple-reads-using-an-event-loop)。我在下面附上了我的所有代码:
# -*- coding=utf-8 -*-
import PySimpleGUI as psg
import os
import RPi.GPIO as GPIO
import time
servoPIN_1 = 17 # Declare GPIO pins for servo signal input
servoPIN_2 = 27
GPIO.setmode(GPIO.BCM) # Declare pin numbering system
GPIO.setup(servoPIN_1, GPIO.OUT)
GPIO.setup(servoPIN_2, GPIO.OUT)
PWM_1 = GPIO.PWM(servoPIN_1, 50) # Create PWM channels w/frequency allocation of 50Hz
PWM_2 = GPIO.PWM(servoPIN_2, 50)
psg.theme('DarkAmber') # Add a touch of color
Top_Def = [[psg.Text("Concept 2: Band Pincher", size=(25,1), font=("Courier", 20))], [psg.HorizontalSeparator()]]
LHS_PreDef = [
[psg.Text("Choose pre-selected routine", font=("Courier", 12))],
[psg.Image('/home/pi/Desktop/Motor-Control_Script/image1.png', size=(301,232)),
psg.Button('Delayed Extension Grip', font=("Courier", 10))],
[psg.Image('/home/pi/Desktop/Motor-Control_Script/image2.png', size=(301,99)),
psg.Button('Simultaneous Extension Grip', font=("Courier", 10))],
[psg.Button('hidden', size=(6,2), button_color=(psg.theme_background_color(),psg.theme_background_color()), border_width=0)]
]
RHS_CustomDef = [
[psg.Text("Create custom servo routine", font=("Courier", 12))],
[psg.Image('/home/pi/Desktop/Motor-Control_Script/image3.png', size=(200,200)),
psg.In(size=(20,1), enable_events=True, key= "_Servo1_"), psg.Button('Actuate servo 1', size=(6,2), font=("Courier", 10))],
[psg.Image('/home/pi/Desktop/Motor-Control_Script/image3.png', size=(200,200)),
psg.In(size=(20,1), enable_events=True, key= "_Servo2_"), psg.Button('Actuate servo 2', size=(6,2), font=("Courier", 10))],
[psg.Button('Exit', size=(6,2), font=("Courier", 10))]
]
Layout = [
[Top_Def,psg.Column(LHS_PreDef),psg.VSeparator(), psg.Column(RHS_CustomDef)]
]
window = psg.Window('Handling solutions', Layout)
while True:
event, values = window.read()
if event == psg.WINDOW_CLOSED or event == 'Exit': # if user closes window or clicks cancel
break
elif event == 'Delayed Extension Grip':
PWM_1.start(9)
PWM_2.start(10)
time.sleep(0.5)
PWM_1.ChangeDutyCycle(6)
time.sleep(1.5) # Sets arbitrary sleep time
PWM_2.ChangeDutyCycle(12)
time.sleep(1.5) # can create user input here to confirm parcel placement
PWM_1.ChangeDutyCycle(8) # Simultaneously enclosed parcel
PWM_2.ChangeDutyCycle(10)
time.sleep(0.05)
PWM_1.stop()
PWM_2.stop()
GPIO.cleanup()
elif event == 'Simultaneous Extension Grip':
PWM_1.start(9)
PWM_2.start(10)
time.sleep(0.5)
PWM_1.ChangeDutyCycle(6)
PWM_2.ChangeDutyCycle(11)
time.sleep(1.5) # can create user input here to confirm parcel placement
PWM_1.ChangeDutyCycle(8) # Simultaneously enclosed parcel
PWM_2.ChangeDutyCycle(10)
time.sleep(0.05)
PWM_1.stop()
PWM_2.stop()
GPIO.cleanup()
elif event == 'Actuate servo 1':
PWM_1.start(0)
PWM_1.ChangeDutyCycle(float(values["_Servo1_"]))
time.sleep(0.05)
PWM_1.stop()
y = values["_Servo1_"]
print(y)
PWM_1.ChangeDutyCycle(float(y))
time.sleep(0.05)
PWM_1.stop()
elif event == 'Actuate servo 2':
PWM_2.start(0)
PWM_2.ChangeDutyCycle(float(values["_Servo2_"]))
time.sleep(0.05)
PWM_2.stop()
window.close()
运行 脚本生成此 GUI image
例如:GUI 接受处理的 Actuate Servo 1 的单个输入。但是,不会处理同一字段中的任何后续输入。我不是很熟悉这个包,所以任何帮助将不胜感激。
它看起来工作正常,但不确定您的 GPIO 命令是否有问题。
布局格式有问题。它应该是元素列表的列表,或者行列表和行是元素列表。
...
Top_Def = [[psg.Text("Concept 2: Band Pincher", size=(25,1), font=("Courier", 20))], [psg.HorizontalSeparator()]]
...
Layout = [[Top_Def,psg.Column(LHS_PreDef),psg.VSeparator(), psg.Column(RHS_CustomDef)]]
...
最好运行你在另一个线程中执行GPIO命令,示例代码如下,这里没有任何测试。
# -*- coding=utf-8 -*-
import threading
from time import sleep
import RPi.GPIO as GPIO
import PySimpleGUI as psg
"""
func = {
("GPIO", "cleanup") : GPIO.cleanp,
("PWM", 1, "start") : PWM1.start,
("PWM", 2, "start") : PWM2.start,
("PWM", 1, "stop") : PWM1.stop,
("PWM", 2, "stop") : PWM2.stop,
("PWM", 1, "DutyCycle") : PWM_1.ChangeDutyCycle,
("PWM", 2, "DutyCycle") : PWM_2.ChangeDutyCycle,
"SLEEP" : sleep,
}
def gpib(window, commands):
result = True
for command in commands:
try:
if command[0] == "PWM":
if len(command) == 4:
func[command[:3]](command[3])
elif len(command) == 3:
func[command[:3]]()
elif command[0] == "SLEEP":
func[command[0]](command[1])
elif command[0] == "GPIO":
func[command[:2]]()
except:
result = False
break
window.write_event_value('-THREAD-', result)
command1 = [("PWM", 1, "start", 9), ("PWM", 2, "start", 10), ("SLEEP", 0.5),
("PWM", 1, "DutyCycle", 6), ("SLEEP", 1.5), ("PWM", 1, "DutyCycle", 12),
("SLEEP", 1.5), ("PWM", 1, "DutyCycle", 8), ("PWM", 2, "DutyCycle", 10),
("SLEEP", 0.05), ("PWM", 1, "stop"), ("PWM", 2, "stop"), ("GPIO", "cleanup")]
"""
font10 = ("Courier", 10)
font12 = ("Courier", 12)
font20 = ("Courier", 20)
psg.theme('DarkAmber') # Add a touch of color
psg.set_options(font=font10)
LHS_PreDef = [
[psg.Text("Choose pre-selected routine", font=font12)],
[psg.Image(data=psg.EMOJI_BASE64_HAPPY_HEARTS),
psg.Button('Delayed Extension Grip')],
[psg.Image(data=psg.EMOJI_BASE64_HAPPY_IDEA),
psg.Button('Simultaneous Extension Grip')],
]
RHS_CustomDef = [
[psg.Text("Create custom servo routine", font=("Courier", 12))],
[psg.Image(data=psg.EMOJI_BASE64_HAPPY_CONTENT),
psg.In(size=(20,1), enable_events=True, key= "_Servo1_"),
psg.Button('Actuate servo 1', size=(15,1))],
[psg.Image(data=psg.EMOJI_BASE64_HAPPY_GASP),
psg.In(size=(20,1), enable_events=True, key= "_Servo2_"),
psg.Button('Actuate servo 2', size=(15,1))],
]
Layout = [
[psg.Column([[psg.Text("Concept 2: Band Pincher", font=font20)]], element_justification='left', expand_x=True),
psg.Column([[psg.Button('Exit', size=(6,2))]], element_justification='right', expand_x=True)],
[psg.HorizontalSeparator()],
[psg.Column(LHS_PreDef), psg.VSeparator(), psg.Column(RHS_CustomDef)],
[psg.Button('hidden', size=(6,2), border_width=0, button_color=
(psg.theme_background_color(), psg.theme_background_color()))],
]
window = psg.Window('Handling solutions', Layout)
while True:
event, values = window.read()
if event in (psg.WINDOW_CLOSED, 'Exit'):
break
elif event == 'Delayed Extension Grip':
print(event)
# threading.Thread(target=gpib, args=(window, command1), daemon=True).start()
elif event == 'Simultaneous Extension Grip':
print(event)
elif event == 'Actuate servo 1':
print(event, values["_Servo1_"])
elif event == 'Actuate servo 2':
print(event, values["_Servo2_"])
elif event == '-THREAD-':
print(event, f'GPIO command {"OK" if values[event] else "NG"}')
window.close()