PySimpleGUI文本元素仅首次更新求助:STM32串口通信场景
PySimpleGUI文本元素仅首次更新串口数据的问题解决
我用以下程序向STM32板发送数据,并将收到的字符串更新到PySimpleGUI的文本元素中。数据能正常发送到板卡,板卡也能正确回复(控制台可以每次打印接收数据),文本元素首次接收数据时也能正常更新,但首次传输后,虽然程序还能打印接收数据,文本元素却不再显示内容(甚至内容消失);如果用另一个元素显示每次传输更新的计数器,计数器却能正常显示。
import PySimpleGUI as sg import serial from serial.tools.list_ports import comports def monitoraSerial(): valoresExibir = '' while True: try: while interfaceSerial.in_waiting > 0: charRecebido = interfaceSerial.read().decode("ascii") if charRecebido == '\n': window['-VALORES-'].update(valoresExibir) valoresExibir = '' else: valoresExibir += charRecebido #window['-VALORES-'].update(interfaceSerial.readline().decode(encoding="ascii")[0:-1]) except: break window.start_thread(monitoraSerial, '-ENCERRASERIAL-') while True: event, values = window.read() if event in (sg.WIN_CLOSED, 'Cancel'): break
接收数据格式为"p: %d, i: %d, d: %d, f: %d\n"。
我已经尝试了以下操作:
- 强制设置
visible属性为True; - 调用
refresh和finalize方法; - 使用
readline方法;
期望'-VALORES-'元素在每次传输时都能更新,但实际仅首次传输时更新,后续内容消失。请问应如何修改?
问题原因与解决方法
核心问题在于子线程中直接操作PySimpleGUI元素不是线程安全的,PySimpleGUI的GUI更新必须在主线程中完成。你的子线程monitoraSerial直接调用window['-VALORES-'].update(),首次可能侥幸成功,但后续会因为线程冲突导致元素更新失效。
修改思路是让子线程把收到的数据发送到主线程,由主线程负责更新GUI元素,具体实现如下:
修改后的完整代码
import PySimpleGUI as sg import serial from serial.tools.list_ports import comports def monitoraSerial(window): valoresExibir = '' while True: try: while interfaceSerial.in_waiting > 0: charRecebido = interfaceSerial.read().decode("ascii") if charRecebido == '\n': # 将数据发送给主线程,触发自定义事件 window.write_event_value('-SERIAL_DATA-', valoresExibir) valoresExibir = '' else: valoresExibir += charRecebido except Exception as e: print(f"串口读取异常: {e}") break # 初始化GUI窗口(示例,可根据需求调整布局) layout = [ [sg.Text("串口数据:"), sg.Text("", key='-VALORES-', size=(30, 1))], [sg.Button("Cancel")] ] window = sg.Window("串口监控", layout, finalize=True) # 初始化串口(根据实际端口、波特率修改) interfaceSerial = serial.Serial('COM3', 9600, timeout=1) # 启动子线程,传入window对象用于线程通信 window.start_thread(lambda: monitoraSerial(window), '-ENCERRASERIAL-') while True: event, values = window.read() if event in (sg.WIN_CLOSED, 'Cancel'): if interfaceSerial.is_open: interfaceSerial.close() break # 处理子线程发来的串口数据事件 elif event == '-SERIAL_DATA-': # 在主线程安全更新GUI元素 window['-VALORES-'].update(values[event]) window.close()
补充说明
- 原代码缺失
window和interfaceSerial的初始化逻辑,修改后的代码补充了示例内容,需根据实际硬件配置调整串口参数; - 子线程通过
window.write_event_value()发送自定义事件,这是PySimpleGUI官方推荐的线程间通信方式,能确保GUI更新的线程安全性; - 如果想用
readline简化代码,子线程可改为:
def monitoraSerial(window): while True: try: line = interfaceSerial.readline().decode("ascii").strip() if line: window.write_event_value('-SERIAL_DATA-', line) except Exception as e: print(f"串口读取异常: {e}") break
内容的提问来源于stack exchange,提问作者EletroEduardo
相关产品推荐
相关产品推荐

