tkinter en python

jjdelcerromurciano en yahoo.es jjdelcerromurciano en yahoo.es
Vie Mayo 20 16:39:08 CEST 2005


No es escesivamente complejo tratar con threads y tkinter. Solo tienes que 
tener en cuenta que nunca deberias hacer cosas como la que propones. Siempre 
es el thread principal el que maneja el gui. Para solucionar esas cosas, 
tkinter te provee de un metodo "after" que tienen todos loc controles 
Tkinter. Con este metodo lo que programas es que pasado cierto tiempo se 
invoque a una funcion, y desde esa funcion tienes acceso completo al gui.

Se podria montar algo como:

from Queue inport Queue
import Threading
import Tkinter

class Ventana(object):
  def __init__(self):
    self._w = TkInter.Tk()
    self._w.pack()
    self._queue = Queue()
    self._threadping = threading.Thread(target=self.__run)
    self._threadping.start()
    self._w.after(2000, self.__checkQueue) 

  def __run(self):
    # Esto se ejecuta en un thread aparte.
   # Desde aqui no se puede tocar el GUI.
    while True:
       .... hago mis cosas ....
      Si tengo algo que pintar:
        self._queue.put("hay que pintar un boton")
       .... sigo haciendo mas cosas ....
     
  def __checkQueue(self):
    # Este metodo lo invoca el GUI cada 2 segundos.
    if self._queue.qsize() > 0:
      accion = self._queue.get()
      ... hago lo que dice la accion ya que esto se ejecuta en el 
      ... thread principal y aqui tengo acceso al GUI.
    self._w.after(2000, self.__checkQueue) # Antes de salir rearmo el timer.

Supongo que habram varios errores de sintaxis y cosas asi en el codigo, pero 
no pretendo dar un codigo funcional , sino una idea a partir de la que 
construyas la solucion a tu problema.

Resumiendo.
- Por un lado tienes el GUI en el que montas un timer que se dispara cada 
cierto tiempo, por ejemplo 2 segundos.

. Por otro montas un thread que es el que haca el trabajo "duro", pero no 
puede acceder al GUI.

- Por ultimo montas una cola y la usas para que el thread envie cosas al GUI, 
y este en el timer va desencolandolas y pintando lo que toque.

Lo suyo seria hacer algo mas elaborado a la hora de meter cosas en la cola, no 
meter strings pelones. Algo como una clase de accion y atributos para los 
parametros que necesite. Si eres mas vago puedes pasarle una tupla o un 
diccionario, pero el codigo queda mas ilegible con el tiempo. Queda mas claro 
algo asi como:

        self._queue.put(ActualizarBoton(text="va bien"))

Que algo como:

        self._queue.put((1,"va bien"))

Eso si en el primer caso tendrias que crear algo como:

class Accion(object):
  def __call__(self, ventana):
    raise RuntimeError, "Deves sobreescribirlo"

class ActualizarBoton(Accion):
  def __init__(self, text):
    Accion.__init__(self)
    self.text ) text
  
  def __call__(self,ventana):
    actualizo el boton de la ventana.

Y en lugar de preguntar por la accion en el __checkQueue simplemente hacer 
algo como:
      accion = self._queue.get()
      accion(self)

En lugar de poner una lista de ifs para ir preguntando por el tipo de accion.


Bueno, creo que ya me he enrrollado mas de la cuenta.
Si no te aclaras o quieres mas cosas, ala , a preguntar, pero no desesperes 
puedo tardar varios dias en leer el correo.

Por cierto, alguien hace una pregunta similar la tuya pero con accesos a BD. 
La solucion puede ser similar, casi todos los toolkits graficos tienen algo 
parecido al "after" del tk o la posibilidad de timers.

Un saludo
Joaquin.

El Wednesday, 18 de May de 2005 21:16, Abel Aranda escribió:
> Buenas tardes, al final lo solucione utilizando un thread, pero sigo con
> la varios problemas....
>
> Tengo el siguiente código.
> Esta parte me dibuja los checkbuttons
>
> global Maquinas
>    for i in Maquinas:
>       self.checkObjects.append(StringVar())
>       self.oneObject =
> Checkbutton(self.personalFrame,text=i.nombre,variable=self.checkObject
> s[-1],anchor='e',onvalue=i.nombre, offvalue="",command =
> self.pulsar,foreground = "#FF0000")
> 	self.listaobjetos.append(self.oneObject)
>     for i,cb in enumerate(self.listaobjetos):
>     		cb.grid(column=i % 4, row=i / 4,sticky = W)
>         	Maquinas[i].posx = i / 4
> 		Maquinas[i].posy = i % 4
>
> Y un tread lanzado
>
> def threads(self):
>     print "lanzando"
>     global Maquinas
>     self.threadping = threading.Thread(target=self.run)
>     self.threadping.start()
>
> ambos dentro del mismo objeto
>
> la cuestion es que desde el trhead quiero modificar la aplicación
> grafica, cambiar el color de un checkburron ( es una maquina ) cuando se
> pierda conectividad con ella, y no se como hacerlo
>
> cada vez que utilizo el metodo boton.grid me da un error desde el thread
>
> mi idea seria hacer algo asi
>
> def run(self)
> 	if maquina se cae:
> 		self.listaobjetos.eliminar_dicho_objeto
> 		self.listaobjetos.insertar_en_la_posicion_en la que
> estaba el
> 		objeto anterior el nuevo pero con un color diferente.
> 		Volver a pintarlo en la posición gris del anterior
> 		Hacer algo parecido a un root.update() para que coja los
> cambios
>
> A ver si hay suerte y alguien puede echarme una mano.
>
> Lo del sondeo lo solucione con el trhead, es un bucle infinito que al
> final tiene un sleep de 20 sg y después de eso sondeo una variable
> global para ver si he de salir del thread y terminar su ejecución.
>
>
> Un Saludo
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> Abel Aranda Arriscado
>    Administrador
>    CEDAS
>
>  Centro de Datos, Administración y Soporte
>    e-mail: abel.aranda en salud.madrid.org
>    tfno: 91 4265549,  móvil: 670726950
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> El contenido de esta comunicación debe considerarse privado y
> confidencial. Si Vd. no es el destinatario y la hubiere recibido por
> error, se le informa que cualquier divulgación, distribución o copia de
> esta comunicación está estrictamente prohibida; por favor, notifíquelo
> inmediatamente al  remitente y elimine este mensaje.
>
>
> This Email is intended for the exclusive use of the addressee only. If
> you are not the intended recipient, you should not use the contents nor
> disclose them to any other person and you should immediately notify the
> sender and delete the Email.
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>
> -----Mensaje original-----
> De: python-es-bounces en aditel.org [mailto:python-es-bounces en aditel.org]
> En nombre de Ernesto Revilla
> Enviado el: lunes, 16 de mayo de 2005 23:20
> Para: La lista de python en castellano
> Asunto: Re: [Python-es] tkinter en python
>
> En tkinter:
>
> class Application:
>     pollInterval=100 # intervalo de poll en milisegundos
>     def __init__(self):
>        self.root=self.createMainWindow()
>        # cualquier cosa aquí
>        self.pollTaks()
>
>
>     def createMainWindow(self):
>        root=Tkinter.Tk()
>        # cualquier cosa para construir interfaz
>        ...
>        return root
>
>     def pollTask(self):
>        # haz lo que quieras aquí
>        ...
>        # casda
>         self.root.after(self.pollInterval,self.pollTask)
>
>
> es decir, usas .after de Tkinter.Tk o cualquier otro widget que hayas
> creado. La sintaxis es:
> widget.after(intervaloEnMilisegundos, metodo, argumento1,
> argumento2....). El propio procedimiento tiene que reregistrarse con
> after si se desea que sea periódico.
>
> Tkinter sólo te va a asegurar que el método no se va a llamar antes. Si
> está ocupado no va a llamar a la función.
>
> Sacado de:
> http://www.pythonware.com/library/tkinter/introduction/
> en concreto:
> http://www.pythonware.com/library/tkinter/introduction/x9507-alarm-handl
> ers-and-other.htm
>
> Erny
>
> Aranda Arriscado, Abel escribió:
> >buenas sigo realizando una plicacion con python y me encuentro con el
>
> siguiente problema,un treao d y la aplicación grafica, y lo que deseo es
> que la aplicacion grafica sondee cada cierto tiempo una variable
> global(siempre va a leer de ella nunca escribir).
>
> >Alguno tiene idea de como se puede hacer esto de forma predeterminada,
>
> algun metodo para que lo estee sondeando desde que arranco la aplicacion
> pero que no me kite el control de esta, por ejemplo que lo sondee cada
> 20 segundos pero pueda seguir trabajando con la aplicacion grafica.
>
> >A ver si alguien me puede ayudar
> >
> >
> >-----------------------------------------------------------------------
>
> -
>
> >_______________________________________________
> >Python-es mailing list
> >Python-es en aditel.org
> >http://listas.aditel.org/listinfo/python-es
______________________________________________ 
Renovamos el Correo Yahoo!: ¡250 MB GRATIS! 
Nuevos servicios, más seguridad 
http://correo.yahoo.es




Más información sobre la lista de distribución Python-es