pysimplegui 更新仅在首次使用时有效

问题描述 投票:0回答:2

以下程序应将数据发送到 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-'
仅在第一次传输时更新,从第二次传输开始消失。

python user-interface python-multithreading pyserial pysimplegui
2个回答
0
投票

避免线程使其工作(也许这个新的更新逻辑可以在线程中工作,但我宁愿不使用一个):

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()

0
投票

也许你可以通过线程接收数据。

演示代码

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()
© www.soinside.com 2019 - 2024. All rights reserved.