From 35f5958c4cd4f78f6d9eb42fbfebf5b341bfdd8d Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Sat, 2 Mar 2019 13:31:34 -0500 Subject: [PATCH] New design pattern --- DemoPrograms/Demo_Multithreaded_Queued.py | 71 +++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 DemoPrograms/Demo_Multithreaded_Queued.py diff --git a/DemoPrograms/Demo_Multithreaded_Queued.py b/DemoPrograms/Demo_Multithreaded_Queued.py new file mode 100644 index 00000000..09ebf8ac --- /dev/null +++ b/DemoPrograms/Demo_Multithreaded_Queued.py @@ -0,0 +1,71 @@ +from queue import Queue +from threading import Thread +from time import sleep + +import PySimpleGUI as sg + +""" + DESIGN PATTERN - Multithreaded GUI + One method for running multiple threads in a PySimpleGUI environment. + This design pattern works for all of the flavors of PySimpleGUI including the Web and also repl.it + +""" + + +def worker_thread(thread_name, run_freq, gui_queue): + """ + A worker thrread that communicates with the GUI + These threads can call functions that block withouth affecting the GUI (a good thing) + :param thread_name: Text name used for displaying info + :param run_freq: How often the thread should run in milliseconds + :param gui_queue: Queue used to communicate with the GUI + :return: + """ + print('Strarting thread - ', thread_name) + i = 0 + while True: + sleep(run_freq/1000) + gui_queue.put('{} - {}'.format(thread_name, i)) + i += 1 + + +def the_gui(gui_queue): + """ + starts and executes the GUI. Returns when the user exits / closes the window + reads data from a Queue and displays the data + :param gui_queue: Queue the GUI should read from + :return: + """ + layout = [ [sg.Text('Your GUI Window')], + [sg.Text('', size=(15,1), key='_OUTPUT_')], + [sg.Button('Exit')],] + + window = sg.Window('Window Title').Layout(layout) + + while True: # Event Loop + event, values = window.Read(timeout=200) # wait for up to 200 ms for a GUI event + if event is None or event == 'Exit': + break + #--------------- Handle stuff coming in from threads --------------- + try: # see if something has been posted to Queue + message = gui_queue.get_nowait() + except: + message = None # indicate nothing posted + # if message received from queue, display the message in the Window + if message: + window.Element('_OUTPUT_').Update(message) + + # if user exits the window, then close the window and exit + window.Close() + + +if __name__ == '__main__': + #-- Create a Queue to communicate with GUI -- + gui_queue = Queue() # queue used to communicate between the gui and the worker + #-- Start worker threads, one runs twice as often as the other + thread = Thread(target=worker_thread, args=('Thread 1', 1000, gui_queue,), daemon=True) + thread.start() + thread = Thread(target=worker_thread, args=('Thread 2', 500, gui_queue,), daemon=True) + thread.start() + #-- Start the GUI passing in the Queue -- + the_gui(gui_queue)