domingo, 14 de agosto de 2011

Usar QtDesigner para actualizar nuestro QHolaMundo

En esta entrada expliqué cómo comenzar con PyQt creando un sencillo QHolaMundo. Ahora voy a explicar cómo usar QtDesigner para recrear nuestro QHolaMundo.

Voy a asumir que ya se tiene instalado Python y PyQt, como lo expliqué en el primer post. En Windows el instalador de PyQt ya trae todas las herramientas necesarias. Para tener las herramientas de edición en Linux debemos instalar los siguientes paquetes:
  • pyqt4-dev-tools
  • designer-qt4
Ya con las herramientas, comenzamos abriendo el QtDesigner:

Seleccionamos la opción Main Window para obtener esto:
Así podremos comenzar a editar nuestra interfaz gráfica. Lo primero que necesitamos (para emular el QHolaMundo original) es un QBoxLayout horizontal. Vamos a las herramientas de la izquierda y arrastramos un Horizontal Layout a nuestra ventana:
Ahora debemos indicarle a nuestra ventana que este layout será su layout por defecto. En la esquina superior derecha del editor encontramos el Object Inspector
Allí seleccionamos nuestra ventana principal (MainWindow) y hacemos clic derecho sobre ella. Aparece un menú contextual en el cual haremos clic en Lay out > Lay out horizontally.

Ahora pondremos los widgets que necesitamos dentro de nuestro layout. En el QHolaMundo original eran un QLineEdit y un QPushButton. Ambos se encuentran en el panel de herramientas:
En el panel de propiedades de la derecha, le pondremos nombres a nuestros componentes

Para preservar los nombres del QHolaMundo original, al campo de texto lo llamaremos leMiNombre y al botón btHola. Ahora viene lo qué hace de QtDesigner tan buen editor: vamos a crear el evento de saludar y lo conectaremos al botón. En QtDesigner todo es visual, hasta esto.

Comencemos con crear un slot. Un slot en Qt es una función que puede ser llamada por un evento (signal). Podemos decir que en Qt los eventos se llaman signals y los métodos que ejecutan éstos son slots. Todo widget puede tener sus signals y slots personalizados. Lo que haremos es crearle un slot a nuestra ventana que se encargará de saludar al usuario. Para ello volvamos al Object Inspector
Volvemos a hacer clic derecho sobre MainWindow, en el menú contextual hacemos clic en Change signals/slots para abrir este diálogo:
Como vemos en la imagen, hacemos clic en el símbolo + verde de los slots para que se agregue un nuevo slot. Lo renombraremos como salude() (debe incluir los paréntesis, esto indica que el slot no recibe parámetros). Aceptamos y ahora nos vamos al modo de edición Signals/Slots ubicado en el toolbar superior
El primer botón de este toolbar es el diseño de componentes estándar. El segundo es el diseño de Signals/Slots. El tercero y el cuarto no lo usaremos por ahora. Al activar el modo de edición de Signals/Slots, haremos clic sostenido sobre el botón y arrastraremos el mouse sobre el espacio vacío de la ventana y allí soltaremos el botón del mouse. Al hacerlo correctamente aparecerá el siguiente cuadro:
Lo que hemos hecho (según muestra el conector rojo), es asociar una señal (signal) del botón a un método (slot) en la ventana. Ahora debemos seleccionar clicked() como la señal a esperar y salude() como nuestro slot receptor, y aceptamos.

Con esto es suficiente de QtDesigner para nuestro sencillo QHolaMundo. Guardamos el archivo en la carpeta que desee. Nos dirigimos a ella y abrimos una ventana de terminal (recordemos que en Windows Vista/7 se abre  haciendo clic derecho+Shift sobre la carpeta y luego Abrir ventana de comandos aquí).

Ahora haremos uso de la consola para convertir nuestro archivo GUI guardado (que debe tener extensión ui si no la cambió) en un script Python. Para ello usaremos la herramienta pyuic4 que viene en la instalación de Windows. En Windows ejecutamos en la consola:

C:\Python25\Lib\site-packages\PyQt4\bin\pyuic4 QHolaMundo.ui -o QHolaMundoGui.py

Esto porque yo tengo Python 2.5, si instaló Python 2.6 se reemplaza Python25 por Python26, y lo mismo con el 2.7. En Linux es más fácil ya que pyuic4 ya está en el path del sistema:

pyuic4 QHolaMundo.ui -o QHolaMundoGui.py

Ahora tendrá un script de python en la misma carpeta donde guardó el ui, llamado QHolaMundoGui.py. A continuación necesitamos ejecutar este aplicativo. Vamos a crear un nuevo script de python en la misma carpeta llamado QHolaMundo.py con el siguiente contenido:

from PyQt4.QtGui import *
import sys
from QHolaMundoGui import Ui_MainWindow

class QHolaMundo(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self,None)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
    def salude(self):
        miNombre = self.ui.leMiNombre.text()
        saludo = 'Hola %s'%(miNombre)
        QMessageBox.information(self,'Saludo',saludo)

app = QApplication(sys.argv)
qhm = QHolaMundo()
qhm.show()
sys.exit(app.exec_())

Encontremos las diferencias con el QHolaMundo original (las he resaltado). Para comenzar, creamos la clase heredada de QMainWindow y no de QWidget, esto porque en el QtDesigner creamos un Main Window. Además hemos reemplazado la creación de los widgets por dos líneas:

self.ui = Ui_MainWindow()
self.ui.setupUi(self)

Lo que hacemos es crear en la propiedad ui de nuestra clase el constructor de widgets (Ui_MainWindow que es la clase que creó pyuic4 en QHolaMundoGui.py). Luego le indicamos que inicialice los widgets en nuestra ventana y listo, ahora nuestra ventana tiene la apariencia que le dimos en QtDesigner. La diferencia con hacerlo directamente (como el QHolaMundo original) es que ahora los widgets no están en la misma ventana, sino dentro de la propiedad ui, es decir, ahora no llamamos al campo de texto con self.leMiNombre, sino con self.ui.leMiNombre. Algo para nada molesto si tenemos en cuenta que nos ha ahorrado código.

Además vemos ahora que no hay que hacer conexiones con signals y slots. QtDesigner ya lo hizo por nosotros, lo único que necesitamos (de no hacerlo saltan errores al ejecutar) es crear en nuestra clase un método por cada slot que hayamos creado en QtDesigner. En este ejemplo sólo fue uno: salude() y como vemos, no recibe parámetros.

Al ejecutar:
Como el original pero más fácil y divertido. Hay muchas más cosas que explorar con QtDesigner, como el exportador de recursos (pyrcc4), una opción muy interesante. En otra oportunidad haremos un navegador usando las librerías WebKit (las de Google Chrome y Safari) que vienen incluidas en PyQt, con QtDesigner.

TIP: si se trabaja mucho con QtDesigner resultará molesto en Windows estar llamando a pyuic4 y pyrcc4 desde su ubicación cada que se desea exportar un archivo ui. Hay soluciones como hacer el comando de exportación en un archivo bat, pero yo prefiero agregar la ubicación del pyuic4 (en mi equipo es C:\Python25\Lib\site-packages\PyQt4\bin) al path del sistema (como en Linux). Así desde donde quiero llamo a pyuic4 por su nombre, sin la dirección completa.

2 comentarios:

Si deseas extender esta entrada, por favor hazlo