以下程序应将数据发送到 STM32 板并使用接收到的字符串更新文本元素。数据被正确发送到电路板,电路板会正确回复(例如,程序每次都可以将接收到的数据打印到控制台)。此外,文本元素会使用第一个接收到的数据正确更新。但是,在第一次传输后,即使程序可以继续打印接收到的数据,它也会隐藏或删除文本,不再显示。如果另一个元素用于显示在每次传输时更新的计数器,则显示该计数器而无需进一步更改。
import PySimpleGUI as sg
import serial
from serial.tools.list_ports import comports
layout = [ [sg.Text('P'), sg.InputText()],
[sg.Text('I'), sg.InputText()],
[sg.Text('D'), sg.InputText()],
[sg.Button('Ok'), sg.Button('Cancel')],
[sg.Text("Valores PID", key='-VALORES-')] ]
parametros = ['p', 'i', 'd']
window = sg.Window('Calibrar PID', layout)
tentarConectar = "OK"
while tentarConectar == "OK":
try:
portas = []
for portaAberta in comports():
portas.append(portaAberta.device)
portaEscolhida = (sg.popup_get_text("Digite o número da porta COM. As opções são:\n" + ", ".join(portas), "Definir COM"))
if portaEscolhida == None:
tentarConectar = "Cancel"
break
portaEscolhida = "COM" + portaEscolhida
interfaceSerial = serial.Serial(port=portaEscolhida, baudrate=115200, timeout=None)
tentarConectar = ""
except:
tentarConectar = sg.popup_ok_cancel("Não conectou", "Para tentar de novo, clique em \"Ok\"")
if tentarConectar == "Cancel":
window.close()
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
for parametro in range(len(parametros)):
if values[parametro]:
try:
valorInteiro = int(values[parametro])
if valorInteiro in range(256):
interfaceSerial.write(bytes(parametros[parametro] + chr(valorInteiro), encoding="ascii"))
else:
sg.popup_ok("intervalo inválido", parametros[parametro] + " está fora do intervalo válido")
except ValueError:
sg.popup_ok("Entrada inválida", parametros[parametro] + " não foi enviado pq não é int")
window.close()
接收到的数据格式为
"p: %d, i: %d, d: %d, f: %d\n"
.
请问我应该改什么?
我试过:
强制
visible
属性到True
;
呼叫
refresh
和finalize
;
readline
方法;
期待
'-VALORES-'
元素在每次传输中更新。
'-VALORES-'
仅在第一次传输时更新,从第二次传输开始消失。
避免线程使其工作(也许这个新的更新逻辑可以在线程中工作,但我宁愿不使用一个):
import PySimpleGUI as sg
import serial
from serial.tools.list_ports import comports
layout = [ [sg.Text('P'), sg.InputText()],
[sg.Text('I'), sg.InputText()],
[sg.Text('D'), sg.InputText()],
[sg.Button('Ok'), sg.Button('Cancel')],
[sg.Text("Valores PID", key='-VALORES-')] ]
parametros = ['p', 'i', 'd']
window = sg.Window('Calibrar PID', layout)
tentarConectar = "OK"
while tentarConectar == "OK":
try:
portas = []
for portaAberta in comports():
portas.append(portaAberta.device)
portaEscolhida = (sg.popup_get_text("Digite o número da porta COM. As opções são:\n" + ", ".join(portas), "Definir COM"))
if portaEscolhida == None:
tentarConectar = "Cancel"
break
portaEscolhida = "COM" + portaEscolhida
interfaceSerial = serial.Serial(port=portaEscolhida, baudrate=115200, timeout=None)
tentarConectar = ""
except:
tentarConectar = sg.popup_ok_cancel("Não conectou", "Para tentar de novo, clique em \"Ok\"")
if tentarConectar == "Cancel":
window.close()
valoresExibir = ''
deveAtualizar = False
while True:
event, values = window.read(timeout=100)
if event in (sg.WIN_CLOSED, 'Cancel'):
break
window.refresh()
if not event == sg.TIMEOUT_KEY:
for parametro in range(len(parametros)):
if values[parametro]:
try:
valorInteiro = int(values[parametro])
if valorInteiro in range(256):
interfaceSerial.write(bytes(parametros[parametro] + chr(valorInteiro), encoding="ascii"))
else:
sg.popup_ok("intervalo inválido", parametros[parametro] + " está fora do intervalo válido")
except ValueError:
sg.popup_ok("Entrada inválida", parametros[parametro] + " não foi enviado pq não é int")
while interfaceSerial.in_waiting > 0:
charRecebido = interfaceSerial.read().decode("ascii")
if charRecebido == '\n':
deveAtualizar = True
else:
valoresExibir += charRecebido
if deveAtualizar:
deveAtualizar = False
window['-VALORES-'].update(valoresExibir)
valoresExibir = ''
window.close()
也许你可以通过线程接收数据。
演示代码
from time import sleep
from datetime import datetime
import threading
import PySimpleGUI as sg
def rfi_reader(window):
# Should call method `window.write_event_value` not in main thread for all GUI updates
global running # flag to stop thread
while running:
sleep(2) # simulate action
message = datetime.now().strftime("%Y/%m/%d %H:%M:%S ") + "New Message"
window.write_event_value('RFI Message', message)
window.write_event_value('End', None) # Event for thread end
font = ('Courier New', 16)
sg.theme('DarkBlue4')
sg.set_options(font=font)
layout = [
[sg.Button('Start'), sg.Button('Exit')],
[sg.StatusBar('', auto_size_text=False, key='Message')],
]
window = sg.Window('GPIO', layout, enable_close_attempted_event=True)
running = False
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSE_ATTEMPTED_EVENT, 'Exit'):
if running:
running = False
else:
break
elif event == 'End': # wait thread end
break
elif event == 'Start' and not running: # Start thread
running = True
threading.Thread(target=rfi_reader, args=(window, ), daemon=True).start()
elif event == 'RFI Message': # Update message from thread
message = values[event]
window['Message'].update(message)
window.close()