domingo, 9 de agosto de 2009

Interfaces gráficas con PyQt

En esta entrada, realizaremos un ejemplo sencillo de PyQt, con el siguiente orden:
  1. Diseño de la interfaz gráfica con QtDesigner.
  2. Generación del código en Python con la herramienta pyuic4.
  3. Creación de una clase para contener el objeto con la ventana y manejar sus eventos, además del punto de entrada (main) para nuestro programa.
Pero, ¿qué es todo esto? Dejemos que la Wikipedia nos ilumine, pues todo está dicho y la vida es corta; ahora, a falta del artículo correspondiente, les puedo decir que QtDesigner es una aplicación para diseñar interfaces gráficas de Qt, almacenando la descripción y disposición de los componentes en un archivo XML, para su posterior uso desde múltiples lenguajes de programación.

Requerimientos.

El sistema usado en la elaboración y prueba de este ejemplo es Debian Sid, por lo que mencionaré el nombre de paquetes propios de la distribución. Sin embargo, las herramientas usadas son multiplataforma.
  • python (podemos usar de la versión 2.4 en adelante).
  • Las librerías de Qt4, que se obtendrán automáticamente por dependencias al instalar python-qt4.
  • python-qt4 (la interfaz entre las librerías Qt4, programadas en C++, y el lenguaje que estaremos usando).
  • qt4-designer.
  • pyqt4-dev-tools (este paquete nos proporciona el comando pyuic4).

Introducción a Python.

Python es un lenguaje muy fácil de aprender, por lo que aún si no lo hemos usado nunca, con un poco de lectura y práctica podremos comenzar con nuestros primeros programas, en un nivel básico, pero funcional.

Les recomiendo leer este tutorial para un rápido inicio. Para entender con facilidad el ejemplo de esta entrada, será necesario conocer la estructura de un programa en Python, los tipos de datos, funciones y en menor medida, herencia, módulos y paquetes.

Entrando en materia.

Nuestro ejemplo está basado de este material, siendo muy recomendable su lectura, y desde la diapositiva 41 se comienza a usar QtDesigner. Les debería quedar algo así:

Los botones que creamos para las cuatro operaciones, tienen los nombres: sum, res, mul y div, por otro lado, los campos de texto se llamarán num1, num2 y result, y por último, a la ventana le hemos llamado calc. Bien, guardaremos este formulario con el nombre calc.ui y ahora viene la magia: con el comando pyuic4 tomaremos ese archivo .ui y generaremos el código en Python. El comando es:
pyuic4 calc.ui -o calc_ui.py

El resultado lo vemos a continuación:

Archivo calc_ui.py

Noten que con QtDesigner hemos hecho todo el trabajo sucio; de haber modificado más propiedades o agregado más componentes, escribir, probar y mantener el código manualmente sería una actividad poco grata.

Aquí hay un punto importante a tratar, y es que cada vez que modifiquemos nuestra interfaz (.ui) tendremos que regenerar el código en Python, por lo que no es nada recomendable hacer cambios a este último, dado que serán sobreescritos sin piedad.

Para complementar el formulario con el código correspondiente a los eventos y algunas otras acciones en tiempo de ejecución, podemos escribir una nueva clase y ahí crear un objeto basado de la clase originada desde QtDesigner, o bien, que esta nueva clase herede de la primera. En esta ocasión haremos lo último.

Archivo calc.py

Una diferencia que vemos entre el código anterior y el mostrado en la diapositiva 57 de la presentación, es que en nuestra clase no hemos controlado el evento clicked() sobre el botón salir. En lugar de ello, hemos definido un manejador para este evento desde el mismo QtDesigner, redirigiéndolo al método close() del formulario. En la diapositiva 44 podemos ver dónde se ubica el editor de señales. Aquí les dejo una captura de esta herramienta:

Lo anterior lo pudimos hacer porque close() forma parte de la clase QWidget, y es lo que se llama un slot, que no es mas que un método diseñado para recibir señales (eventos) y con un comportamiento definido. No hay que olvidar que desde QtDesigner no podemos agregar código, así que nuestros métodos para responder a los clicks sobre los botones tendrán que ser implementados y "conectados" de manera externa.

Comentando algo más sobre el código, de las líneas 13 a 16 vemos la forma en que enlazamos unas señales específicas de los botones, con cuatro diferentes métodos ubicados en la misma clase (línea 18 a la 28). El bloque de la línea 30 en adelante está fuera de la definición de la clase, y será ejecutado cuando este módulo sea invocado como punto de entrada de la aplicación.

Para ejecutar el programa:
python calc.py


Bueno, ahí tenemos ya nuestra potente calculadora en ejecución. En alguna entrada posterior veremos los cambios o inconvenientes que surjan al hacer todo esto en windows, y en cosas más importantes, usaremos el otro método de comunicación entre QtDesigner y Python, que es cargar directamente el archivo .ui en tiempo de ejecución, es decir, sin generar previamente el código con pyuic4.

Enlaces y adjuntos.

Python para todos
Presentación sobre PyQt
pyqt-calculadora.zip

4 comentarios:

  1. El artículo es muy ilustrativo y además suena interesante el tema, habrá que darle una revisada. Ya tengo instaldo el QtDesigner aca en windows, pero me late que mejor lo probare con linux para ver lo del comando de python.
    Tengo una duda, se podrán convertir las interfarces a VFP 9 (joke).

    ResponderEliminar
  2. Muy buen articulo fer !!!, me tomare un poquito de tiempo para probarlo (lectura y practica), gracias ahora tengo una guia rapida para probar python :).

    ResponderEliminar
  3. Excelente Fer!!
    Esto me recuerda cuando estaba probando "tepache", diseñaba las interfaces con "Glade" y mediante "tepache" ligaba la interfaz a python. Recuerdo que esto vino a hablar Sandino Flores en uno de los cilcos de conferencias de SL que hubieron en la UNACH.

    ResponderEliminar
  4. No me sale el codigo dice que no importa signal estoy usando qt5 y python 3.2.3

    ResponderEliminar