S0yboi
S0yboi

Reputation: 25

PySimpleGUI: How to process persistent user inputs?

I've created a simple GUI to control two servos. The GUI works fine if the user only has a single input, however, it fails to process persistent user inputs. I've looked at the PysimpleGUI cookbook demo for persistent user inputs, however, I cant seem to implement the same type of solution into my code (Link: https://pysimplegui.readthedocs.io/en/latest/cookbook/#recipe-pattern-2a-persistent-window-multiple-reads-using-an-event-loop). I've attached all of my code below:

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

Running the script produces this GUI image

For example: The GUI takes a single input for Actuate Servo 1 which is processed. However, any subsequent inputs into the same field are not processed. I'm not very familiar with the package, so any help would be appreciated.

Upvotes: 0

Views: 532

Answers (1)

Jason Yang
Jason Yang

Reputation: 13051

It looks work fine and not sure if there's something wrong in your GPIO commands.

There' something wrong about the format of layout. It should be a list of lists of elements, or list of rows and row is list of elements.

...
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)]]
...

Better to run you GPIO commands in another thread, example code as following, no any testing here.

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

Upvotes: 0

Related Questions