From 4daa0a6a524eca972ca29a01dd38228516e1ed55 Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Fri, 19 Feb 2021 22:20:20 -0500 Subject: [PATCH] New Demo - indirectly call sg.popup from a thread --- DemoPrograms/Demo_Multithreaded_popup.py | 83 ++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 DemoPrograms/Demo_Multithreaded_popup.py diff --git a/DemoPrograms/Demo_Multithreaded_popup.py b/DemoPrograms/Demo_Multithreaded_popup.py new file mode 100644 index 00000000..6c8370cb --- /dev/null +++ b/DemoPrograms/Demo_Multithreaded_popup.py @@ -0,0 +1,83 @@ +import threading +import time +import PySimpleGUI as sg +import queue + +""" + Threading Demo - "Call popup from a thread" + + Can be extended to call any PySimpleGUI function by passing the function through the queue + + + Safest approach to threading is to use a Queue object to communicate + between threads and maintrhead. + + The thread calls popup, a LOCAL function that should be called with the same + parameters that would be used to call opiup when called directly + + The parameters passed to the local popup are passed through a queue to the main thread. + When a messages is received from the queue, sg.popup is called using the parms passed + through the queue + + Copyright 2021 PySimpleGUI.org +""" + +mainthread_queue:queue.Queue = None + +def popup(*args, **kwargs): + if mainthread_queue: + mainthread_queue.put((args, kwargs)) + +def the_thread(): + """ + The thread that communicates with the application through the window's events. + + Once a second wakes and sends a new event and associated value to the window + """ + i = 0 + while True: + time.sleep(2) + popup('Hello, this is the thread', 'My counter value', i, text_color='white', background_color='red', non_blocking=True) + i += 1 + + +def process_popup(): + try: + queued_value = mainthread_queue.get_nowait() + sg.popup_auto_close(*queued_value[0], **queued_value[1]) + except queue.Empty: # get_nowait() will get exception when Queue is empty + pass + + +def main(): + """ + The demo will display in the multiline info about the event and values dictionary as it is being + returned from window.read() + Every time "Start" is clicked a new thread is started + Try clicking "Dummy" to see that the window is active while the thread stuff is happening in the background + """ + global mainthread_queue + + mainthread_queue = queue.Queue() + + layout = [ [sg.Text('Output Area - cprint\'s route to here', font='Any 15')], + [sg.Multiline(size=(65,20), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True, reroute_cprint=True)], + [sg.T('Input so you can see data in your dictionary')], + [sg.Input(key='-IN-', size=(30,1))], + [sg.B('Start A Thread'), sg.B('Dummy'), sg.Button('Exit')] ] + + window = sg.Window('Window Title', layout, finalize=True) + + while True: # Event Loop + event, values = window.read(timeout=500) + sg.cprint(event, values) if event != sg.TIMEOUT_EVENT else None + if event == sg.WIN_CLOSED or event == 'Exit': + break + process_popup() + if event.startswith('Start'): + threading.Thread(target=the_thread, daemon=True).start() + window.close() + + +if __name__ == '__main__': + main() \ No newline at end of file