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