tkinter en python
Abel Aranda
Abel.aranda en salud.madrid.org
Vie Mayo 20 17:00:42 CEST 2005
Muchísimas gracias, este mail me ha aclarado muchas cosas sobre como
debería hacerlo, ya os comentare pq la aplicación que toy desarrollando
se va a quedar parada por los examenes 3 semanas, pero este mail me ha
dado un concepto mucho mas claro de cómo tengo que hacerlo aunque seguro
que tendre que preguntar un par de cosas mas jeje pero como a simple
vista parecen obvias esperare a desesperarme pa plantearlas.
Saludos
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 jjdelcerromurciano en yahoo.es
Enviado el: viernes, 20 de mayo de 2005 16:39
Para: python-es en aditel.org
Asunto: Re: [Python-es] tkinter en python
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
_______________________________________________
Python-es mailing list
Python-es en aditel.org
http://listas.aditel.org/listinfo/python-es
Más información sobre la lista de distribución Python-es