Pedro Augusto Boller
Pedro Augusto Boller

Reputation: 33

How do I update the text in PySimpleGUI in real time?

I'm trying to make a program that reads the serial of my arduino and shows the information in real time in a GUI. The problem is that I don't know how to make the data update in real time.

This is my current code:

import re
import serial
import PySimpleGUI as sg

class InterfaceGrafica:
    def __init__(self):
        layout = [[sg.Text('Interface gráfica para o controle do secador.')],
                  [sg.Text('Valor do controle PWM:'), sg.Text(Dados().pwm, key = 'pwm')],
                  [sg.Text('Valor da temperatura: '), sg.Text(Dados().temp, key = 'temp')],
                  [sg.Text('Peso: '), sg.Text(Dados().peso, key = 'peso')],
                  [sg.Text('Valor da umidade: '), sg.Text(Dados().um, key = 'um')],
                  [sg.Text('Temperatura setpoint: '), sg.Text(Dados().set, key = 'set')],
                  [sg.Button('Exit')]]

        self.janela = sg.Window('Versão final', layout=layout, size=(600, 600))

    def Iniciar(self):
        while True:
            self.event, self.values = self.janela.Read()
            if self.event == sg.WIN_CLOSED or self.event == 'Exit':
                break
            conecao = serial.Serial("COM3", 9600)

            for i in range(20):
                leitura = conecao.readline()
                leiturad = leitura.decode()
                var = re.split(',', leiturad)
                print(leiturad)
                self.janela.Element('pwm').Update(values=var[0])
                janela.Refresh
                self.janela.Element('temp').Update(values=var[1])
                self.janela.Element('peso').Update(values=var[2])
                self.janela.Element('um').Update(values=var[3])
                self.janela.Element('set').Update(values=var[4])

tela = InterfaceGrafica()
tela.Iniciar()

Upvotes: 3

Views: 3985

Answers (2)

Jason Yang
Jason Yang

Reputation: 13061

Using multi-thread, or your GUI will be no respond when your code blocked at reading com port.

Following code not tested for no com port input, so somewhere maybe typo error or something wrong.

import serial   # pip install PySerial
import threading
import PySimpleGUI as sg

class GUI:
    def __init__(self):
        sg.theme('DarkBlue3')
        sg.set_options(font=("Courier New", 16))
        layout = [
            [self.center([[sg.Text('Controller of Dryer', font=("Courier New", 20, 'bold'))]])],
            [sg.Text("")],
            [sg.Text('PWM        '), self.Text('PWM'     )],
            [sg.Text('TEMPERATURE'), self.Text('TEMP'    )],
            [sg.Text('WEIGHT     '), self.Text('WEIGHT'  )],
            [sg.Text('MOISTURE   '), self.Text('MOISTURE')],
            [sg.Text('SETPOINT   '), self.Text('SETPOINT')],
            [sg.Text("")],
            [self.center([[sg.Button('Exit')]])],
        ]
        self.window = sg.Window('Final version', layout=layout, finalize=True)
        self.running = True
        self.com = serial.Serial("COM3", 9600)
        threading.Thread(target=self.get_data, args=(window,), daemon=True).start()
        self.start()

    def center(self, layout):
        return sg.Column(layout, element_justification='center', expand_x=True)

    def Text(self, key):
        return sg.Text('', size=(20, 1), text_color='white', background_color='blue', key=key)

    def get_data(self):
        while self.running:
            data = com.readline().decode().split(",")
            self.window.write_event_value("DATA", data)

    def start(self):
        while True:
            event, values = self.window.read()
            if event in (sg.WIN_CLOSED, 'Exit'):
                break
            elif event == 'DATA':
                data = values[event]
                self.update(data)
        self.running = False
        self.window.close()

    def update(self, data):
        for i, key in enumerate(('PWM', 'TEMP', 'WEIGHT', 'MOISTURE', 'SETPOINT')):
            self.window[key].update(value=data[i])

GUI()

Upvotes: 0

Doyousketch2
Doyousketch2

Reputation: 2147

You need to set a timeout for self.janela.read( timeout=250 )
I created a fake Dados to test, (which you don't have to use), and it updates.

https://pysimplegui.readthedocs.io/en/latest/

#! /usr/bin/env python3
##  pip3 install serial pysimplegui
##  Python -m pip install serial pysimplegui

import re
import serial
import random
import PySimpleGUI as sg

class Singleton( object ):
    def __new__( cls ):
        if not hasattr( cls, 'instance' ):
            cls .instance = super( Singleton, cls ) .__new__( cls )
        return cls .instance

Dados = Singleton()

def update():
    print( 'update' )
    Dados .pwm = random .random()
    Dados .temp = f'{ random .randint( 50, 100 ) } *F'
    Dados .peso = f'$ { random .randint( 1, 30 ) }'
    Dados .um = random .randint( 1, 100 )
    Dados .set = random .randint( 1, 100 )


class InterfaceGrafica:
    def __init__(self):
        layout = [ [ sg .Text('Interface gráfica para o controle do secador.') ],
                   [ sg .Text('Valor do controle PWM:'),  sg .Text( Dados .pwm,  key='pwm' ) ],
                   [ sg .Text('Valor da temperatura: '),  sg .Text( Dados .temp,  key='temp' ) ],
                   [ sg .Text('Peso: '),  sg .Text( Dados .peso,  key='peso' ) ],
                   [ sg .Text('Valor da umidade: '),  sg .Text( Dados .um,  key='um' ) ],
                   [ sg .Text('Temperatura setpoint: '),  sg .Text( Dados .set,  key='set' ) ],
                   [ sg .Button('Exit') ] ]

        self.janela = sg.Window( 'Versão final', layout=layout, size=(400, 300) )

        while True:
            self.event, self.values = self.janela.read( timeout=250 )
            if self.event == sg.WIN_CLOSED or self.event == 'Exit':
                break
            '''
            conecao = serial.Serial("COM3", 9600)
            for i in range(20):  leitura = conecao.readline()  ##  read 20 lines from serial

            leiturad = leitura.decode()  ##  decode those 20 lines
            var = re.split(',', leiturad)  ##  split CSV into list
            print(var)
            '''

            self.janela['pwm']( Dados .pwm )  ##  var[ 0 ]
            self.janela['temp']( Dados .temp )  ##  var[ 1 ]
            self.janela['peso']( Dados .peso )  ##  var[ 2 ]
            self.janela['um']( Dados .um )  ##  var[ 3 ]
            self.janela['set']( Dados .set )  ##  var[ 4 ]
            self.janela.Refresh()
            update()

update()
InterfaceGrafica()

Upvotes: 2

Related Questions