miércoles, mayo 16, 2007

Opensource Flash

Esta es una pagina que abrió hace poco y trata sobre las distintas alternativas libres a la plataforma Macromedia Adobre Flash. Es interesante para la gente que se dedica a los multimedios, acá les dejo el Link: http://www.osflash.org/

martes, mayo 15, 2007

PyQt en Windows

La instalación de PyQt4 en mi Debian Sid no tuvo mayores inconvenientes, es más, era uno de lo s paquetes que había instalado para correr algunos scripts de SuperKaramba (si, ya se PyQt3, pero bueno, cuando fui a Synpatics vi que tenía tambien la version 4)
A raíz de una inquietud que me surgió de las complicaciones que tuvo Latuaro para compilar PyQt, decidí ver que tan complicado era.
Notar que es una instalación de Qt/C++ al comienzo, la parte de PyQt son los últimos pasos.
Vamos por Qt...
  • Bajé primero MinGW (que ahora es tipo Cygwin, te bajas un exe chiquito, y cuando lo ejecutas te baja gcc, g++, make, etc. solito de internet, hice una instalación full). Luego me daría cuenta que no era necesario, pero bueno, yo creía que había que compilar algo...
    Para los que no conozcan MinGW, es un port de gcc a windows, similar a cygwin.
    (Al momento de la ejecutar este MinGW-5.1.2.exe me advierte de que hay una versión más nueva, no le hice caso, después de todo, acababa de bajarlo!)
  • Luego bajé la versión _binaria_ de Qt para windows(qt-win-opensource-4.2.3-mingw.exe), en la pagina de Trolltech, dije que deseaba realizar desarrollo Open Source, hay que fijarse que sea la que termina en -mingw.exe
    Para varias bajé Vim 7.1 y Mc, aunque nada pude hacer contra la consola antinatural de windows, que ni de tamaño se puede cambiar con facilidad :(
  • Comienza la instalación (de Qt), me pregunta donde está MinGW, se lo apunto (C:\mingw), me dice que la versión que soporta es la 3.2, luego avisa que no encuentra w32api.h. Pero el archivo está, obviamente que con el nuevo estadar de C++, es decir, sin el .h final. Despues de eso la instalacion termina sin problema, y me genera en el menú inicio los accesos al diseñador, lingüista, asistente, etc. Y un par de bat para meter las variables de Qt en el Path. Tomé todas las variables y las puse en el Path del sistema, este sería el paso que haría a la versión compilada de PyQt4 funcionar.
    Así quedaron las variables de entorno:
    ALLUSERSPROFILE=C:\Documents and Settings\All Users
    APPDATA=C:\Documents and Settings\defo\Datos de programa
    CLASSPATH=.;C:\Archivos de programa\QuickTime\QTSystem\QTJava.zip
    CLIENTNAME=Console
    CommonProgramFiles=C:\Archivos de programa\Archivos comunes
    COMPUTERNAME=YGGDRASIL-GHOST
    ComSpec=C:\WINDOWS\system32\cmd.exe
    FP_NO_HOST_CHECK=NO
    HOMEDRIVE=C:
    HOMEPATH=\Documents and Settings\defo
    LANGUAGE=es
    LOGONSERVER=\\YGGDRASIL-GHOST
    MCC_INCLUDE=C:\MCC18\h;
    MCHOME=C:\MC
    NUMBER_OF_PROCESSORS=1
    OS=Windows_NT
    Path=C:\MCC18\mpasm;C:\MCC18\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\Syste
    m32\Wbem;C:\Archivos de programa\QuickTime\QTSystem\;C:\MCC18\mpasm;C:\MCC18\bin
    ;C:\Python25;C:\MinGW\bin;C:\MCC18\mpasm;C:\MCC18\bin;C:\Python25;C:\MinGW\bin;"
    C:\Archivos de programa\Vim\vim71";C:\Qt\4.2.3\bin;C:\MinGW\bin;C:\Python25\Lib\
    idlelib
    PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
    PROCESSOR_ARCHITECTURE=x86
    PROCESSOR_IDENTIFIER=x86 Family 15 Model 47 Stepping 0, AuthenticAMD
    PROCESSOR_LEVEL=15
    PROCESSOR_REVISION=2f00
    ProgramFiles=C:\Archivos de programa
    PROMPT=$P$G
    QMAKESPEC=win32-g++
    QTDIR=C:\Qt\4.2.3
    QTJAVA=C:\Archivos de programa\QuickTime\QTSystem\QTJava.zip
    SESSIONNAME=Console
    SystemDrive=C:
    SystemRoot=C:\WINDOWS
    TEMP=C:\DOCUME~1\defo\CONFIG~1\Temp
    TMP=C:\DOCUME~1\defo\CONFIG~1\Temp
    USERDOMAIN=YGGDRASIL-GHOST
    USERNAME=defo
    USERPROFILE=C:\Documents and Settings\defo
    windir=C:\WINDOWS
    Probé una pequeña app en Qt y funcionó perfectamente.
  • Luego fui a por PyQt de la pagina de Riverbank y bajé la version binaria (no el codigo fuente, ni SIP, me advierte que no incluye Qt, pero es algo que ya tengo instalado).

    Luego de instalarlo, realizé los imports, como hemos visto en los anteriores posts y todo funcionó perfectamente. Como podrán ver:

Espero que les halla servido como para orientarse, y tengan en cuenta que esta es una instalación de desarrollo, para el end-user se puede automatizar todo el proceso.
Finalmente les dejo las URLs de la documentación de PyQt. Es del propio sitio de Riverbank:

domingo, mayo 13, 2007

Decoradores en Python

Es una interesante característica que incluye Python 2.4 en adelante.
Veamos un pequeño ejemplo:

#! /usr/bin/python

import time

def decorador(funcion):
def nueva(*lista_args):
tiempo1 = time.time()
valor = funcion(*lista_args)
tiempo2 = time.time()
delta = tiempo2 - tiempo1

print "La funcion '%s()' tardo en ejecutarse %s segundos" % (funcion.func_name, delta)
return valor
return nueva

@decorador
def func(a, b):
return a - b

func(2, 3)

Como resultado produce:

[nahuel@valhalla workspace]$ python deco.py
La funcion 'func()' tardo en ejecutarse 4.05311584473e-06 segundos

Hay mucho más en Charming Python: Decorators make magic easy (en inglés)

Conectando eventos en PyQt

Ahora que conocemos los rudimentos de PyQt, es hora de hacer algo cuando el usuario interactúa con la GUI.
Para esto usaremos el connect (método de QObject).
Veamos el siguiente ejemplo, (ha sido lo más simple que se me ha ocurrido
Como verán esta vez no lo hice desde la consola sino desde el editor de texto (de donde saqué los colores bonitos).

#! /usr/bin/python
'''
Un ejemplo de conexion de eventos en PyQt4
'''

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Ventana(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# Redimencionar la ventana
self.resize(QSize(QRect(0,0,400,110).size())) #.expandedTo(Form.minimumSizeHint()))
boton = QPushButton("Pulsame", self)
# Agrandar el boton
boton.setGeometry(QRect(100,20,80,27))
QWidget.connect(boton, SIGNAL("clicked()"), self.un_metodo )
# ahora lo conectamos con otro
def un_metodo(self):
print "hola"

# algo que quizas se podría llamar main()
def principal():
app = QApplication(sys.argv)
v = Ventana()
v.show()
app.exec_()

# lo que se ejecuta cuando llamamos al script
if __name__ == "__main__":
principal()

A esta altura comenzarán a chocarse, si es que ya no lo han hecho con no conocer los métodos de las clases de Qt, a veces dir(), type() y el método __doc__ de los objetos no es suficiente y requerimos algo más solido.
Para esto está QtAssistant (o simplemente assistant, o assistant-qt4) desde la consola. Es "la ayuda" que sale cuando pulsamos F1 sobre un widget en el diseñador.
Para finalizar los invito a volver a la consola y ver que interesante idea de modularidad tiene python (digamos que el script de más arriba se llama eje.py).


[nahuel@valhalla Documents]$ python
Python 2.4.4 (#2, Jan 13 2007, 17:50:26)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import eje
>>> eje.principal()
>>>

Espero que ya le estén agarrando el gustito! Les advierto que es muy adictivo!

PyQt, usando interfases creadas con Designer

Una vez que creamos un archivo .ui en QtDesigner, existen dos formas de usarlo en nuestra aplicación:
  1. Compilarlo con pyuic
  2. Cargarlo dinámicamente mediante el modulo PyQt4.uic
Vemos el punto 1. Vamos a la consola, en el directorio donde hallamos guardado el .ui con el Designer, ejecutamos:
pyuic mi_archivo.ui
Si tienen ambas versiones de PyQt, quizás el comando sea pyuic4, si les da el error:
pyuic: File generated with too recent version of Qt Designer (4.0 vs. 3.3.7)
Vemos que todo el código es lanzado por la salida estándar, para eso usaremos el operador > para mostrarlo:
pyuic mi_archivo.ui > mi_clase.py
Muy bien, ahora tendremos las clase, mi_clase que tendrá en su interior la clase que inicializa la interfase sobre el widget que hemos elegido como base (QDialog, QWidget, QMainWidget...).
Ahora desde la consola python en el mismo directorio podemos hacer:

[nahuel@valhalla ~]$ python
Python 2.4.4 (#2, Jan 13 2007, 17:50:26)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from PyQt4.QtGui import *
>>> from PyQt4.QtCore import *
>>> import mi_clase
>>> dir(mi_clase)
['QtCore', 'QtGui', 'Ui_Form', '__builtins__', '__doc__', '__file__', '__name__', 'sys']
>>> class MiVentana(QWidget, mi_clase.Ui_Form):
... """ Heredo del Widget y de la clase que compile con pyuic """
... def __init__(self, *args):
... # Lo primero es llamar al padre
... QWidget.__init__(self, *args)
... # ahora uso un metodo que define Ui_Form para generar la interfase
... self.setupUi(self)
... print "Creacion de una ventana" # un mensajito como para avisar
...
>>> # ahora creamos el contexto de aplicacion Qt (QApplication)
...
>>> import sys
>>> app = QApplication(sys.argv)
>>> v = MiVentana()
Creacion de una ventana
>>> # ohhh, magico, no?
...
>>> v.show()
>>> # a correr.......
...
>>> app.exec_()
0

y obtenemos esto:
Bueno, aquí también les dejo el UI, que como verán es un XML.


Ahora vamos con el método dinámico(2), ya que se han tragado estos ultimos 3 posts sobre PyQt vamos a comenzar a ir más rápdio, si se complica me avisan, ok?

[nahuel@valhalla ~]$ python
Python 2.4.4 (#2, Jan 13 2007, 17:50:26)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from PyQt4.QtCore import *
>>> from PyQt4.QtGui import *
>>> # El modulo compilador de UIs
...
>>> from PyQt4 import uic
>>> # Veamos que tiene
...
>>> dir(uic)
['Compiler', 'PYQT_VERSION_STR', 'StringIO', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__path__', '_display_code', '_header', 'compileUi', 'compiler', 'exceptions', 'indenter', 'loadUi', 'loadUiType', 'objcreator', 'properties', 'time', 'uiparser']
>>> # Veamos la documentacion del metodo que usaremos...
...
>>> uic.loadUi.__doc__
'loadUi(uifile, baseinstance=None) -> widget\n\n Load a Qt Designer .ui file and return an instance of the user interface.\n\n uifile is a file name or file-like object containing the .ui file.\n baseinstance is an optional instance of the Qt base class. If specified\n then the user interface is created in it. Otherwise a new instance of the\n base class is automatically created.\n '
>>> # Bueno, vamos a probarlo
...
>>> import sys
>>> app = QApplication(sys.argv)
>>> ventana = uic.loadUi('./mi_clase.ui')
>>> ventana.show()
>>> app.exec_()
0
>>>
Espero que se hallan divertido viendo la flexibilidad que tiene PyQt para generar interfases.
Si están dudando que mecanismo usar el dinámico o el compilado, eso va a depender de que tan frecuentemente cambien la GUI. Los más osados podrían recompilar dinámicamente su .ui y de esa manera emular un Makefile...
Bueno, no les complico más, hagan los ejemplos, y cualquier problema me avisan,

PyQt un poco más allá

Bueno, seguiré explicando lo que he ido aprendiendo sobre PyQt.
Existe un editor de interfases para Qt, se llama QtDesigner, aunque el binario suele llamarse simplemente designer (ojo si tienen las dos versiones de 3 y 4, pueden tener más de uno).
Así es como se ve:
y lo que nos permite es diagramar visualmente nuestras ventanas en el modo edito de ventanas:
y nos permite conectar eventos entre elementos de la GUI en el modo señales y zóclos:
En este modo podemos conectar una evento de un componente visual (widget) con un zócalo de otro (por ejemplo, que al pulsar un botón se cierre la ventana).
Les recomiendo este video para que vean visualmente el tema de la conexión de eventos.
No teman a que escriben un poco de código en C++, al final, esto no se aplica a PyQt.

Python y Qt, primeros pasos

Luego de la charla del Lug sobre Desarrollo derápido de aplicaciones web con Python/Django, he tenido un poco de tiempo para incursionar el el terreno de las GUIs y Python, a raíz de que las GUIs en Java con SWING y SWT han sido un buen fiasco, al menos para mi.
Hay muchos toolkits para generar GUIs, pero me decanté por PyQt debido principalmente a que tenía un poquito de experiencia con C++ y Qt (la cual me parece muy buena por su velocidad y facilidad de aprendizaje).
PyQt no goza de tanta documentación (específica de Python) como otros toolkits para ventanas como PyGTK o wxPython, pero en principio no es un problema ya que PyQt es es si un wrapper(envoltura) de Qt/C++ (es decir, para una clase QWidget en C++ tenemos un QWidget en Python, etc.).
Antes de seguir, tengo que advertirles que PyQt3 es ligeramente distinto a PyQt4, recomiendo este último en lo posible debido a las nuevas características que se han añadido en Qt4, sobre todo en la versión 4.2.

Bueno, ahora vamos con un ejemplo sencillo:

[nahuel@valhalla ~]$ python
Python 2.4.4 (#2, Jan 13 2007, 17:50:26)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from PyQt4.QtCore import *
>>> from PyQt4.QtGui import *
>>> import sys
>>> # los dos primeros imports son de Qt y este ultimo es para obtener los argumentos
...
>>> # Ahora creamos la apliacion
...
>>> app = QApplication(sys.argv)
>>> ventana = QWidget()
>>> ventana.show()
>>> # Ahora le damos las riendas a Qt
...
>>> app.exec_()
0