Refresco tkinter de texto recibido en un callback

Iniciado por minak, 11 Mayo 2018, 11:58 AM

0 Miembros y 1 Visitante están viendo este tema.

minak

Hola estoy haciendo un pequeño programa en python que escucha un servidor mqtt y lo muestra en pantalla en el modo consola no tengo problema pero quise poner una gui con tkinter y no se como hacer que cuando el callback de mensaje recibido refresque un text que esta dentro de una clase que corresponde a la ventana principal. Me podéis ayudar a ver como puedo hacerlo por que es lo unico que me falta y no se me ocurre.

Ventana Principal
class MyApp:
   def __init__(self, parent):
       self.parent = parent  
       self.parent.protocol("WM_DELETE_WINDOW", self.on_closing) #Indicas que cuando presiones la x de cerrar ventana

       #Ventana principal
       root.title(proyect +" "+ version)                      
       root.resizable (True, True)
       root.iconbitmap('pyc.ico')
       #root.geometry ("650x400")
       root.config (bg="black",bd="10", relief ="sunken")

       ventanainfo = Frame()
       ventanainfo.grid()
       #ventanainfo.config (bg="white", width ="630", height ="380", bd="10", relief ="sunken", cursor ="pirate")
       ventanainfo.config (bg="white", bd="10", relief ="sunken", cursor ="arrow")


       #Configuracion de elemetos sobre frame Principal
       #*****PANTALLA LOG**************
       pantallaLOG = Text(ventanainfo, width ="90", height ="18")
       pantallaLOG.grid (row="0", column ="0", padx=1,pady=1,rowspan=4)
       scrollLog = Scrollbar (ventanainfo, command = pantallaLOG.yview)
       scrollLog.grid (row="0", column ="1", padx=1,pady=1, sticky = "nSeW",rowspan=4)
       pantallaLOG.config (yscrollcommand = scrollLog.set)

       pantallaLOG.insert(INSERT, 'test.\n')
       global ultimoMensaje;
       pantallaLOG.insert(INSERT, ultimoMensaje +'\n')


Callback
def on_message(client, userdata, msg):
   
   global ultimoMensaje
   ultimoMensaje = (time.strftime("%d/%m/%y - %H:%M -> ")+"[" + msg.topic+"] "+str(msg.payload))
   print (ultimoMensaje)

Dejo el main desde el que se inician callback
if __name__ == "__main__":

    openConfig(); 

    myIP = getipextern()
    print (myIP)

    client = mqtt.Client(client_name)
    client.username_pw_set(user, password=password)
    client.on_connect = on_connect
    client.on_disconnect = on_disconnect
    client.on_publish = on_publish
    client.on_message = on_message
    #client.on_log = on_log              # Descomenta para activar el modo Debug
    client.on_subscribe = on_subscribe   # Callback de una supcripcion

    #Comienzo del GUI de usuario

    root = tk.Tk()
    app = MyApp(root)
   
    #****Bucle**********************
    root.mainloop()

    #*** Salida del programa
    print("Cerrando...")
    try:
        client.disconnect()
        client.loop_stop()
    except:
        print ("No procede desconectar")
    print ("Adios")


El programa es mucho mas grande pero es que son mas de 500 lineas para ponerlo aqui. Lo que quiero conseguir es que ese cuadro sea como una consola donde se vaya escribiendo lo que pasa en el programa.
Muchas gracias

minak

#1
Encontre una solucion pero no la entiendo y no es la mejor opcion porque me crea una ventana trasera que entiendo que es para hacer un bucle de refresco el caso que pongo lo que modifique.
Esta parte no entiendo porque se tiene que hacer asi pero si no lo hago asi after no me deja usarla dentro de la funcion.
class MyApp(tk.Tk):
   def __init__(self, parent, *args, **kwargs):
       tk.Tk.__init__(self, *args, **kwargs)

y añado esta funcion

   def update_logtext(self):
       if (ultimoMensaje!=""):

           global ultimoMensaje;
           self.pantallaLOG.insert(INSERT, ultimoMensaje +'\n')
           ultimoMensaje =""

       self.after(1000, self.update_logtext)


Ahora mientras encuentro otra solucion voy a ver si consigo que la ventana secundaria que se crea sea invisible.

PD : Hecho invisible pero no comprendo muy bien todo esto que hize

class MyApp(tk.Frame):
   def __init__(self, parent):
       tk.Frame.__init__(self)


Os pongo el codigo del que saque la solucion por si alguien lo quiere :
import Tkinter as tk
import time

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.clock = tk.Label(self, text="")
        self.clock.pack()

        # start the clock "ticking"
        self.update_clock()

    def update_clock(self):
        now = time.strftime("%H:%M:%S" , time.gmtime())
        self.clock.configure(text=now)
        # call this function again in one second
        self.after(1000, self.update_clock)

if __name__== "__main__":
    app = SampleApp()
    app.mainloop()