2024-02-03 15:17:47 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
import PySimpleGUI as sg
|
|
|
|
|
|
|
|
"""
|
|
|
|
Demo - State Machine using timers
|
|
|
|
|
|
|
|
State Machines are very useful when you need to perform a series of operations that you
|
|
|
|
cannot do all at once due to a time constraint. Particularly problematic are operations
|
|
|
|
where you would normally use "sleeps" as part of the sequence.
|
|
|
|
|
|
|
|
In this Demo Program, we're going to use the PySimpleGUI Timer API calls to provide our
|
|
|
|
sleep-like behavior.
|
|
|
|
|
|
|
|
The sequence of operations we're going to run are:
|
|
|
|
User clicks a "Send" Button to start the sequence:
|
|
|
|
1. A "Status Window" is shown that says "Sending" and Disable SEND button
|
|
|
|
2. Sleep for 3 seconds
|
|
|
|
3. Close the "Status Window"
|
|
|
|
4. Sleep for 2 seconds
|
|
|
|
5. Enable SEND button and Go to state 1
|
|
|
|
|
|
|
|
Control of the state machine will be through the PySimpleGUI events. This will enable you to use threads
|
|
|
|
for any of these states and have the threads communicate the state transitions using the same write_event_value used
|
|
|
|
in this example.
|
|
|
|
|
|
|
|
Copyright 2024 PySimpleSoft Inc.
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
class State:
|
|
|
|
stopped = 'stopped'
|
|
|
|
start = 'start'
|
|
|
|
delay_3_sec = 'delay 3 seconds'
|
|
|
|
close_win = 'close win'
|
|
|
|
delay_2_sec = 'delay 2 seconds'
|
|
|
|
enable_send = 'enable send'
|
|
|
|
|
|
|
|
|
|
|
|
TIMER1 = 3000
|
|
|
|
TIMER2 = 2000
|
|
|
|
NEXT_STATE = '-NEXT-'
|
|
|
|
|
|
|
|
|
|
|
|
def make_send_window():
|
|
|
|
layout = [[sg.Text('Send Window')],
|
|
|
|
[sg.Text('State:'), sg.Text(key='-STATE-')]]
|
|
|
|
|
|
|
|
# Create window a little lower on screen so windows don't overlap
|
|
|
|
window = sg.Window('Send Window', layout, finalize=True, relative_location=(0, 150))
|
|
|
|
return window
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
layout = [[sg.Text('State Machine Example', font='_ 14')],
|
|
|
|
[sg.Text('Click Send to begin sequence')],
|
|
|
|
[sg.Text('State:'), sg.Text(key='-STATE-')],
|
|
|
|
[sg.Button('Send', key='-SEND-'), sg.Button('Exit')]]
|
|
|
|
|
|
|
|
window = sg.Window('State Machine Example', layout, font='Any 12')
|
|
|
|
|
|
|
|
window_send = None
|
|
|
|
state = State.stopped
|
|
|
|
|
|
|
|
while True:
|
|
|
|
event, values = window.read()
|
|
|
|
if event == sg.WIN_CLOSED or event == 'Exit':
|
|
|
|
break
|
|
|
|
|
|
|
|
if event == '-SEND-':
|
|
|
|
state = State.start
|
|
|
|
elif event == NEXT_STATE:
|
|
|
|
state = values[event]
|
|
|
|
|
|
|
|
window['-STATE-'].update(state)
|
|
|
|
if window_send:
|
|
|
|
window_send.refresh()
|
|
|
|
|
|
|
|
# ----- STATE MACHINE PROCESSING -----
|
|
|
|
if state == State.start:
|
|
|
|
window['-SEND-'].update(disabled=True)
|
|
|
|
window_send = make_send_window()
|
|
|
|
window.write_event_value(NEXT_STATE, State.delay_3_sec)
|
2024-02-03 15:55:14 +00:00
|
|
|
elif event == sg.TIMER_KEY and state == State.delay_3_sec: # be sure the if with the timer check AND state is above if with only state
|
|
|
|
window.write_event_value(NEXT_STATE, State.close_win)
|
2024-02-03 15:17:47 +00:00
|
|
|
elif state == State.delay_3_sec:
|
|
|
|
window.timer_start(TIMER1, repeating=False)
|
|
|
|
elif state == State.close_win:
|
|
|
|
window_send.close()
|
|
|
|
window_send = None
|
|
|
|
window.write_event_value(NEXT_STATE, State.delay_2_sec)
|
2024-02-03 15:55:14 +00:00
|
|
|
elif event == sg.TIMER_KEY and state == State.delay_2_sec:
|
|
|
|
window.write_event_value(NEXT_STATE, State.enable_send)
|
2024-02-03 15:17:47 +00:00
|
|
|
elif state == State.delay_2_sec:
|
|
|
|
window.timer_start(TIMER2, repeating=False)
|
|
|
|
elif state == State.enable_send:
|
|
|
|
window['-SEND-'].update(disabled=False)
|
|
|
|
window.write_event_value(NEXT_STATE, State.stopped)
|
|
|
|
|
|
|
|
window.close()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|