Changed multi-threaded demos to use new Window.write_event_value method

This commit is contained in:
PySimpleGUI 2020-07-18 13:42:32 -04:00
parent 934cea5881
commit 04dfa364d5
6 changed files with 109 additions and 139 deletions

View file

@ -1,11 +1,8 @@
#!/usr/bin/python3
import queue
import threading
import time
import PySimpleGUI as sg
# This program has been tested on all flavors of PySimpleGUI and it works with no problems at all
# To try something other than tkinter version, just comment out the first import and uncomment the one you want
"""
DESIGN PATTERN - Multithreaded Long Tasks GUI
@ -13,18 +10,20 @@ import PySimpleGUI as sg
The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
The "long work" is contained in the thread that is being started.
A queue.Queue is used by the threads to communicate with main GUI code
July 2020 - Note that this program has been updated to use the new Window.write_event_value method.
This method has not yet been ported to the other PySimpleGUI ports and is thus limited to the tkinter ports for now.
Internally to PySimpleGUI, a queue.Queue is used by the threads to communicate with main GUI code
The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined,
a Window is created, and an event loop is executed.
What's different is that within this otherwise normal PySimpleGUI Event Loop, there is a check for items
in the Queue. If there are items found, process them by making GUI changes, and continue.
This design pattern works for all of the flavors of PySimpleGUI including the Web and also repl.it
You'll find a repl.it version here: https://repl.it/@PySimpleGUI/Async-With-Queue-Communicationspy
"""
def long_operation_thread(seconds, gui_queue):
def long_operation_thread(seconds, window):
"""
A worker thread that communicates with the GUI through a queue
This thread can block for as long as it wants and the GUI will not be affected
@ -34,7 +33,7 @@ def long_operation_thread(seconds, gui_queue):
"""
print('Starting thread - will sleep for {} seconds'.format(seconds))
time.sleep(seconds) # sleep for a while
gui_queue.put('** Done **') # put a message into queue for GUI
window.write_event_value('-THREAD-', '** DONE **') # put a message into queue for GUI
def the_gui():
@ -44,7 +43,6 @@ def the_gui():
Returns when the user exits / closes the window
"""
sg.theme('Light Brown 3')
gui_queue = queue.Queue() # queue used to communicate between the gui and the threads
layout = [[sg.Text('Long task to perform example')],
[sg.Output(size=(70, 12))],
@ -57,29 +55,17 @@ def the_gui():
# --------------------- EVENT LOOP ---------------------
while True:
event, values = window.read(timeout=100)
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
elif event.startswith('Do'):
try:
seconds = int(values['-SECONDS-'])
print('Thread ALIVE! Long work....sending value of {} seconds'.format(seconds))
threading.Thread(target=long_operation_thread,
args=(seconds, gui_queue,), daemon=True).start()
except Exception as e:
print('Error starting work thread. Bad seconds input: "%s"' %
values['-SECONDS-'])
seconds = int(values['-SECONDS-'])
print('Thread ALIVE! Long work....sending value of {} seconds'.format(seconds))
threading.Thread(target=long_operation_thread, args=(seconds, window,), daemon=True).start()
elif event == 'Click Me':
print('Your GUI is alive and well')
# --------------- Check for incoming messages from threads ---------------
try:
message = gui_queue.get_nowait()
except queue.Empty: # get_nowait() will get exception when Queue is empty
message = None # break from the loop if no more messages are queued up
# if message received from queue, display the message in the Window
if message:
print('Got a message back from the thread: ', message)
elif event == '-THREAD-':
print('Got a message back from the thread: ', values[event])
# if user exits the window, then close the window and exit the GUI func
window.close()