Creating threaded popups in PySimpleGUI

Question:

I have trouble creating either multiple windows or popups using PySimpleGUI.
Each window/popup is supposed to be called from a seperate thread and timeout after 2 seconds.
Using following implementation results in (as expected) this error: main thread is not in main loop.
How do I fix that?

def get_info():
    while True:
        info = get_details()
        if info:
            layout[]
            window = sgWindow(...)
            while True:
                
                
                event, values = window.read(timeout=1000*2)
                if event in (sg.WIN_CLOSED,): break
                if event in ('__TIMEOUT__',):
                    window.close()
                    break
                if event == "X":
                    window.close()
                    close = True
                    break
                if event == "Y":
                    window.close()
                    close = True
                    break

for i in range(x):

    t = threading.Thread(target=get_info())
    t.start()
Asked By: Arr0gant God

||

Answers:

This isn’t possible because PySimpleGUI is not thread-safe. This means that you can only use it in the main thread of your program.

To fix this error, you can use a queue to communicate between the main thread and the other threads. Each thread can add an event to the queue, and the main thread can read from the queue and handle the events as they come in. This way, you can still use PySimpleGUI in the main thread while running your other code in separate threads.

import threading
import queue
import PySimpleGUI as sg

# Create a queue to communicate between threads
q = queue.Queue()

# Define a function to run in a separate thread
def get_info():
    while True:
        # Check if we need to exit the thread
        if x:
            break
        
        # Create a window and show it
        layout = []
        window = sg.Window('Window', layout)
        window.finalize()
        window.show()
        
        # Read events from the window
        while True:
            event, values = window.read(timeout=1000*2)
            if event in (sg.WIN_CLOSED,):
                break
            if event in ('__TIMEOUT__',):
                # Add an event to the queue to close the window in the main thread
                q.put('close_window')
                break
            if event == "X":
                # Add an event to the queue to close the window and set the "close" flag in the main thread
                q.put('close_window_and_flag')
                break
            if event == "Y":
                # Add an event to the queue to close the window and set the "close" flag in the main thread
                q.put('close_window_and_flag')
                break

# Start the thread
t = threading.Thread(target=get_info())
t.start()

# Main loop
while True:
    # Check for events in the queue
    if not q.empty():
        event = q.get()
        if event == 'close_window':
            # Close the window in the main thread
            window.close()
        elif event == 'close_window_and_flag':
            # Close the window and set the "close" flag in the main thread
            window.close()
            close = True
Answered By: newbie