a vueltas con pymedia
Antonio Castro
acastro en ciberdroide.com
Jue Oct 21 09:13:52 CEST 2004
On Wed, 20 Oct 2004, Iñigo wrote:
> Hola:
> Os comenté hace unos días que había hecho una pequeña aplicación con
> Python que al pulsar en un botón reproducía un fichero mp3, y que tenía
> un problema porque al pulsar el botón de reproducir el control no vuelve
> a la ventana, sino que se queda medio bloqueada hasta que termina la
> reproducción del audio. Bueno, pues hoy he vuelto a ponerme a ver si era
> capaz de arreglarlo pero no soy capaz. Os pego el código del archivo .py
> (pythoncard genera dos ficheros uno con extensión.rsrc.py en el que está
> el diseño físico de la interfaz y otro .py donde están las clases,
> gestores de eventos y demás) por si a alguien se le ocurre la solución
> al problema.
>
> Un saludo y gracias por adelantado.
>
> #!/usr/bin/python
>
> """
> __version__ = "$Revision: 1.10 $"
> __date__ = "$Date: 2004/04/24 22:13:31 $"
> """
>
> from PythonCard import model
> [...]
> if __name__ == '__main__':
>
> app = model.Application(Principal)
> app.MainLoop()
Antes que nada decirte que no conozco nada de PythonCard y por lo tanto
todo lo que te diga no dejan de ser meras intuiciones basadas en similitudes
con Tkinter. En Tkinter existe un bucle 'mainloop()' donde se realiza la
recogida y tratamiento de eventos. Cualquier código que se demore en retornar
está interrumpiendo el tratamiento de eventos que supongo es lo mismo que te
está pasando a ti. Te comento de forma muy resumida la solución que yo usé
para lanzar comandos del SO desde Tkinter pero creo que la idea te servirá.
class mkmt_os:
def def __init__(self, root):
self.root=root
self.runing_LinesPopenTask=0
def LinesPopenTask(self, comando):
self.runing_LinesPopenTask=1
...
fdin, fdout, fderr=os.popen3(comando, 'r')
...
self.runing_LinesPopenTask=0
def WaitEndTask(self):
while self.runing_LinesPopenTask:
self.root.after(250) # Esperar un cuarto de segundo.
self.root.update() # !! Refrescar !!
def LinesPopen(self, comando):
if self.runing_LinesPopenTask==1:
self.Warning("Ya hay una tarea en marcha.", 2)
return
self.runing_LinesPopenTask=1;
# Lanzamos una tarea desde un thread.
# OJO: Tkinter no es reentrante. Evitar llamadas a Tkinter
t = threading.Thread(target=self.LinesPopenTask, args=(comando,))
t.start()
self.WaitEndTask() # Espera activa para no interrumpir el bucle
# de eventos de Tkinter
La solución basada en threads es bastante flexible ya que el bucle de
espera no tiene porque limitarse a refrescar de vez en cuando el bucle de
eventos, pero no es la única posibilidad. Tratandose de Tkinter podría haber
usado un bucle con un after(delay_ms, callback, args) que termine llamandose a
si mismo. (Lo que haría sería programar una llamada a si misma pasado cierto
tiempo a modo de interrupción y no necesitaría update() porque ya refresca el
bucle de eventos internamente.) Ignoro las posibilidades en PythonCard pero
debería existir alguna forma de refrescar el bucle de eventos.
--
Un saludo
Antonio Castro
/\ /\
\\W//
_|0 0|_
+-oOOO-(___o___)-OOOo---------------------+
| . . . . U U . Antonio Castro Snurmacher |
| . . . . . . . acastro en ciberdroide.com |
+()()()---------()()()--------------------+
Más información sobre la lista de distribución Python-es