如何将PySimpleGUI的更新信息传递给运行中的线程
解决PySimpleGUI向运行中线程传递参数的问题
你的核心问题有两个:一是Update按钮的事件没被处理,二是线程直接调用窗口read方法存在线程安全风险。下面直接给出修正后的代码,并说明关键改动:
关键问题分析
- 原代码里只监听了输入框
-INPUT-的事件,没有处理Update按钮的点击事件,导致点击按钮时不会触发参数更新。 - 线程中调用
window.read(timeout=0)不符合PySimpleGUI的线程安全规则——所有窗口操作必须在主线程执行,跨线程访问窗口可能引发异常或不可预期的行为。
修正后的代码
import threading import PySimpleGUI as sg import time # 用共享字典传递参数,线程安全 shared_params = {'input_value': ''} def long_running_task(thread_event, update_event): while not thread_event.is_set(): # 模拟长期运行任务 time.sleep(1) # 检查是否有参数更新 if update_event.is_set(): update_event.clear() # 读取共享参数,无需操作窗口 new_value = shared_params['input_value'] print(f"收到GUI更新的参数: {new_value}") print("线程退出") def main(): sg.theme('LightGrey1') layout = [ [sg.Button('启动线程'), sg.Button('更新参数'), sg.Button('停止线程')], [sg.InputText(key='-INPUT-')], [sg.Output(size=(50, 10))] ] window = sg.Window('长期运行线程示例', layout) thread_event = threading.Event() update_event = threading.Event() thread = None while True: event, values = window.read(timeout=100) if event in (sg.WINDOW_CLOSED, 'Exit'): break if event == '启动线程': if not thread or not thread.is_alive(): thread_event.clear() update_event.clear() # 线程只接收事件和共享参数,不直接操作窗口 thread = threading.Thread(target=long_running_task, args=(thread_event, update_event)) thread.start() print("线程已启动") elif event == '停止线程': if thread and thread.is_alive(): thread_event.set() thread.join() print("线程已停止") elif event == '更新参数': # 主线程更新共享参数,然后触发事件通知线程 shared_params['input_value'] = values['-INPUT-'] update_event.set() print("已触发参数更新通知") window.close() if __name__ == '__main__': main()
改动说明
- 新增共享参数字典:
shared_params用来存放需要传递给线程的参数,主线程负责更新,线程负责读取,避免跨线程操作窗口。 - 处理Update按钮事件:在主循环中捕获
更新参数按钮的点击事件,更新共享参数后设置update_event,通知线程读取新参数。 - 线程不再操作窗口:线程只通过事件和共享字典与主线程交互,完全遵守PySimpleGUI的线程安全要求。
这样修改后,点击更新参数按钮时,输入框的内容会被传递给运行中的线程,控制台会打印收到的参数,你可以清晰确认按钮是否生效。
内容的提问来源于stack exchange,提问作者Rick Cromer
相关产品推荐
相关产品推荐

