¿Cómo puede actualizar un GUI con información de una función o archivo adyacente?

Estoy tratando de crear un panel sensor que actualiza cada segundo o dos que dibuja información de Open Hardware Monitor. He creado una función que produce una lista de valores relacionados con la información deseada, sin embargo no puedo conseguir que actualice el GUI. Esta es una versión reducida que sólo muestra la temperatura del paquete CPU. Se mostrará el valor inicial cuando se ejecute, pero no se actualizará. Planeo crear un archivo ejecutable de este código que se puede ejecutar en una pantalla terciaria para dar estadísticas constantes en mi computadora.

import tkinter as tk
import wmi as w

root = tk.Tk()
i=0
def initialize():

    def update():
        w1 = w.WMI(namespace="root\OpenHardwareMonitor")
        temperature_infos = w1.Sensor()
        names = ['CPU Package' , 'GPU Core', 'CPU Total']
        values = [0.0 , 0.0, 0.0, 0.0, 0.0,0.0,0.0,0.0,0.0]
        for sensor in temperature_infos:
            if sensor.SensorType == u'Temperature':
                if sensor.Name == names[0]:
                    values[0] = sensor.Value
                elif sensor.Name == names[1]:
                    values[1] = sensor.Value
                else:
                    pass
            elif sensor.SensorType == u'Load':
                if sensor.Name == names[2]:
                    values[2] = sensor.Value
                elif sensor.Name == names[1]:
                    values[3] = sensor.Value
                elif sensor.Name == u'GPU Memory':
                    values[4] = sensor.Value
                elif sensor.Name == u'Memory':
                    values[5] = sensor.Value
                else:
                    pass
            elif sensor.SensorType == u'Clock':
                if sensor.Name == u'CPU Core #8':
                    values[6] = sensor.Value
                else:
                    pass
            elif sensor.SensorType == u'Fan':
                if sensor.Name == u'Fan #5':
                    values[7] = sensor.Value
                elif sensor.Name == u'GPU Fan':
                    values[8] = sensor.Value
                else:
                    pass
        return values
    values = update()
    text = tk.StringVar()
    text.set(values[0])
    label1 = tk.Label(root, textvariable = text)
    global i
    if i == 0:
         label1.pack()
         i+=1
    else:
        label1.config(textvariable = text)
   
    root.after(1000,initialize)


root.after(1000,initialize)
root.mainloop()

Pregunta hecha hace 3 años, 5 meses, 0 días - Por binarymaestro


3 Respuestas:

  • No uso Windows así que no puedo usar el módulo wmi pero en cuanto a mí debe ser:

    Yo creo vacío Label sólo una vez - al principio - y uso after(1000, update) para ejecutar función que obtiene valores de get_values() y actualiza el texto en la etiqueta label.config(text=...). No crea nuevo Label, No tiene que comprobar si necesita pack o config. No necesita StringVar (pero francamente podría usarlo y entonces no necesitaría label.config)

    import tkinter as tk
    import wmi as w
    
    # --- functions ----
    
    def get_values():
        w1 = w.WMI(namespace="root\OpenHardwareMonitor")
        temperature_infos = w1.Sensor()
        names = ['CPU Package' , 'GPU Core', 'CPU Total']
        values = [0.0 , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
    
        for sensor in temperature_infos:
            if sensor.SensorType == u'Temperature':
                if sensor.Name == names[0]:
                    values[0] = sensor.Value
                elif sensor.Name == names[1]:
                    values[1] = sensor.Value
                #else:
                #    pass
            elif sensor.SensorType == u'Load':
                if sensor.Name == names[2]:
                    values[2] = sensor.Value
                elif sensor.Name == names[1]:
                    values[3] = sensor.Value
                elif sensor.Name == u'GPU Memory':
                    values[4] = sensor.Value
                elif sensor.Name == u'Memory':
                    values[5] = sensor.Value
                #else:
                #    pass
            elif sensor.SensorType == u'Clock':
                if sensor.Name == u'CPU Core #8':
                    values[6] = sensor.Value
                #else:
                #    pass
            elif sensor.SensorType == u'Fan':
                if sensor.Name == u'Fan #5':
                    values[7] = sensor.Value
                elif sensor.Name == u'GPU Fan':
                    values[8] = sensor.Value
                #else:
                #    pass
    
        return values
    
    def update():
        values = get_values()
        label.config(text=values[0])
        root.after(1000, update)
    
    # --- main ---
    
    root = tk.Tk()
    
    label = tk.Label(root)
    label.pack(padx=20, pady=20)
    
    root.after(1000, update)
    root.mainloop()
    

    Versión que emula cambios en values y todo el mundo puede correr

    import tkinter as tk
    
    # --- functions ----
    
    def get_values():
        import random
        values = [0.0 , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
        values[0] = random.randrange(0, 1000)/10 # float value 0.0 ... 100.0
        return values
    
    def update():
        values = get_values()
        label.config(text=values[0])
        root.after(1000, update)
    
    # --- main ---
    
    root = tk.Tk()
    
    label = tk.Label(root)
    label.pack(padx=20, pady=20)
    
    root.after(1000, update)
    root.mainloop()
    

    EDIT:

    Lo mismo con StringVar() en lugar de label.config(text=...)

    import tkinter as tk
    
    # --- functions ----
    
    def get_values():
        import random
        values = [0.0 , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
        values[0] = random.randrange(0, 1000)/10
        return values
    
    def update():
        values = get_values()
        label_var.set(values[0])
        root.after(1000, update)
    
    # --- main ---
    
    root = tk.Tk()
    
    label_var = tk.StringVar()  # to keep value as string
    #label_var = tk.IntVar()    # to keep value as integer
    #label_var = tk.DoubleVar() # to keep value as float
    
    label = tk.Label(root, textvariable=label_var)
    label.pack(padx=20, pady=20)
    
    root.after(1000, update)
    root.mainloop()
    

    Respondida el Dec 17, 2020 a las 01:29 - por webweaverx

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando se debe a que estás creando una nueva instancia de label1 en cada llamada a la función initialize, lo cual provoca que se añadan nuevos labels en lugar de actualizar el existente. Para solucionar esto, debes crear el label fuera de la función initialize y luego actualizar su texto en lugar de crear uno nuevo en cada iteración.

    Aquí te dejo una versión corregida de tu código:

    python
    import tkinter as tk
    import wmi as w
    
    root = tk.Tk()
    label1 = tk.Label(root)
    label1.pack()
    names = ['CPU Package' , 'GPU Core', 'CPU Total']
    values = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
    
    def update():
        w1 = w.WMI(namespace="root\OpenHardwareMonitor")
        temperature_infos = w1.Sensor()
    
        for sensor in temperature_infos:
            if sensor.SensorType == u'Temperature':
                if sensor.Name == names[0]:
                    values[0] = sensor.Value
    
        text.set(values[0])
    
        root.after(1000, update)
    
    def initialize():
        global text
        text = tk.StringVar()
        label1.config(textvariable=text)
    
        update()
    
    initialize()
    root.mainloop()
    

    En este código, creamos el label label1 fuera de la función initialize y lo actualizamos directamente dentro de la función update. Además, inicializamos el label con un textvariable text y actualizamos este textvariable en cada iteración para reflejar el valor actualizado de la temperatura del paquete CPU. Finalmente, llamamos a initialize una sola vez al inicio y luego la función update se encarga de manejar la actualización del GUI cada segundo.

    Respondida el Dec 18, 2020 a las 01:29 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • La función update no está siendo llamada periódicamente para actualizar los valores del GUI. Para actualizar el GUI con los nuevos valores, debes llamar a update cada segundo o dos y luego actualizar el valor del StringVar que está vinculado a la Label. Aquí tienes el código modificado:

    python
    import tkinter as tk
    import wmi as w
    
    root = tk.Tk()
    i = 0
    
    def initialize():
        def update():
            w1 = w.WMI(namespace="root\\OpenHardwareMonitor")
            temperature_infos = w1.Sensor()
            names = ['CPU Package' , 'GPU Core', 'CPU Total']
            values = [0.0 , 0.0, 0.0, 0.0, 0.0,0.0,0.0,0.0,0.0]
            for sensor in temperature_infos:
                if sensor.SensorType == u'Temperature':
                    if sensor.Name == names[0]:
                        values[0] = sensor.Value
                    elif sensor.Name == names[1]:
                        values[1] = sensor.Value
                    else:
                        pass
                elif sensor.SensorType == u'Load':
                    if sensor.Name == names[2]:
                        values[2] = sensor.Value
                    elif sensor.Name == names[1]:
                        values[3] = sensor.Value
                    elif sensor.Name == u'GPU Memory':
                        values[4] = sensor.Value
                    elif sensor.Name == u'Memory':
                        values[5] = sensor.Value
                    else:
                        pass
                elif sensor.SensorType == u'Clock':
                    if sensor.Name == u'CPU Core 

    8':

    values[6] = sensor.Value else: pass elif sensor.SensorType == u'Fan': if sensor.Name == u'Fan

    5':

    values[7] = sensor.Value elif sensor.Name == u'GPU Fan': values[8] = sensor.Value else: pass return values values = update() text = tk.StringVar() text.set(values[0]) label1 = tk.Label(root, textvariable=text) global i if i == 0: label1.pack() i += 1 else: label1.config(textvariable=text) root.after(1000, initialize) root.after(1000, update)

    Llama a update cada segundo

    root.after(1000, initialize) root.mainloop()

    También he eliminado la parte donde configurabas el StringVar dentro del bloque if i == 0. Esto no es necesario ya que el valor del StringVar se actualiza cada vez que se llama a update.

    Respondida el Dec 18, 2020 a las 01:36 - por Gemini

    Votos positivos: 0 | Votos negativos: 0