lunes, 6 de febrero de 2012

Aplicaciones con Interfaz grafica Python (GUI)

Prácticamente cualquier aplicación comercial que quiera hacerse debe contar con tres patas fundamentales.

Lógica programática.
Interfaz grafica
Base de datos.

Hablando desde mi experiencia personal, les cuento que yo me recibí en la facultad como Licenciado en Informática sin haber escrito nunca un programa que contuviera estas tres patas completas. Por lo cual cuando llego la hora de ponerme a laburar, no me sentía completamente capacitado para hacer sistemas.
Cuando salí de la facultad era un muy buen programador de scripts, pero un pésimo Programador de aplicaciones de escritorio.

Si bien la lógica de un programa suele ser la parte más compleja, es la primera que se aprende y esta bien que así sea. Desde nuestros comienzos cuando estudiamos cualquier lenguaje de programación y escribimos nuestros primeros algoritmos ya estamos desarrollando la lógica computacional que puede servir para resolver problemas de casi cualquier índole. El problema surge cuando queremos tomar datos o mostrar los resultados en una pantalla que sea amigable para el usuario final.
Ahí es cuando entra la Interfaz Grafica de Usuario también conocida como GUI. El tema es que cuando comencé a programar utilizaba Pascal o C, los cuales tienen un soporte para generar interfaces grafica muy muy pobres, luego “evolucione” a Visual Basic y a Java pero así y todo no terminaba de convencerme la manera en que se manejaban estas cuestiones. Por suerte apareció PyQt en mi vida…. J
En lo referente a las Bases de datos, en un primer momento lo hacia en archivos de Texto plano en donde tenia que ocuparme de TOOOOOODAAAA la lógica, para asegurar la integridad de los datos, trabajo tedioso si los hay. Luego comencé a trabajar con bases de datos relacionales pero haciendo todo a mano. Y por ultimo descubrí la “magia” de los ORM… Seba esta Feliz.. J  

Comencemos a ver algunas cositas pequeñas.

Como creo que ya dije en alguna oportunidad hoy en día (Febrero de 2012) me encuentro programando en Python 2.6, y para lo que son las interfaces graficas utilizo PyQt GPL v4.4.3 for Python v2.6. Como en el ejemplo que presentare a continuación usaremos Sqlite les recomiendo bajarse el Sqlite Manager del siguiente enlace:


PyQT tiene la particularidad de que genera archivos XML que luego pueden compilarse para generar interfaces graficas que se puedan utilizar en varios lenguajes, entre los que se encuentran C y Python entre otros.

El ejemplo que haremos será sencillo, crear un formulario que acepte 3 campos, Nombre, Apellido y dirección y que tenga tres botones, uno para guardar los datos en la Base de datos, otro para resetear el formulario y otro para cerrar.



Abrimos el Designer de PyQT y generamos la siguiente pantalla… Es muy intuitivo para utilizar, así que no me pondré a explicar paso a paso como hacerla (Si tenes dudas comenta, pregunta, googlea y seguro que obtenes respuesta)



Renombramos el formulario en el editor de propiedades que aparece a la derecha.




Modificamos el titulo de la ventaja tocando la propiedad siguiente:




La convención que utilizo para los nombres de los botones es btn<Accion>.


Agregamos tres labels con los textos:

Nombre
Apellido
Direccion

A los labels a menos que sea completamente necesarios le dejo el nombre por defecto que le pone PyQt.

Agregamos tres controles de los denominados lineEdit y los nombramos txtNombre, txtApellido y txtDireccion.

La pantalla final queda de la siguiente manera:


La guardamos con el nombre FormCargarPersona.ui.

Vamos a agregar un evento a un botón desde el PyQt Designer. Primero vamos a Edit Signals/Slots



Oprimimos clic derecho sobre el botón cerrar y luego arrastramos y soltamos sobre el fondo del Form. Se mostrara algo similar a esto:



Y se nos abrirá la siguiente pantalla. Sobre la parte izquiera se observan las señales habilitadas que puede enviar el boton:

clicked(), clicked(bool), pressed(). Etc..


Seleccionamos clicked() y checkeamos donde aparece la leyenda Show signals and slots inherited form QWidget. Nos apareceran mas opciones:



Seleccionamos clicked() y close(), y le damos click al boton Aceptar.

Volvemos a la edición de widget común clickeando en Edit Widgets



Y probamos que todo ande como nosotros queremos. Con CTRL+R corremos el formulario, ahora si pinchamos sobre el botón cerrar el mismo debería cerrarse.

Guardamos y listo por ahora… :)

Si editamos el archivo ui con un editor de texto, veremos que es código puramente XML.
Para compilarlo a lo que

Para compilar el código XML a código Python se utiliza un compilador llamado Pyuic4 que se encuentra por lo general en el Path: C:\Python25\Lib\site-packages\PyQt4 dependiendo la versión de Python que tengamos instalada.

Abrimos una consola y nos paramos en el Path en donde guardamos el archivo FormCargarPersona.ui. En ese lugar ejecutamos el siguiente comando:

>pyuic4 –x FormCargarPersona.ui –o FormCargarPersona.py



Esto generara en la carpeta C:\Python25\Lib\site-packages\PyQt4> el archivo FormCargarPersona.py. Cabe aclarar que no es recomendable modificar este archivo auto-generado. No es recomendable modificarlo, ya que ante cualquier modificación en la interfaz grafica, deberemos volver a compilar el archivo ui y esta compilación pisara cualquier cambio que se haya realizado en dicho archivo.

Por ahora pondremos todo en una misma carpeta, pero luego es aconsejable utilizar algún árbol de directorios como puede llegar a ser el siguiente:

Por gusto personal cuando debo crear una aplicación utilizo el sistema árbol de directorios, no es mi estilo decir cual es la forma correcta de trabajar.. J.. para mi la forma correcta es la que nos queda cómoda y da resultados…



En la carpeta archivos, guardo archivos que genere con mi aplicación, archivos de Texto, reportes en PDF y demás cuestiones.

En la carpeta Base de datos guardo todo lo referente a la conexión con la Base de datos, la creación de tablas, y las Clases de negocio que luego serán las que mapeo por medio del ORM con las tablas propiamente dichas.

En la carpeta diálogos guardo los códigos fuentes de lo que vendría a ser el controlador de las vistas… Al trabajar con Qt es casi obligatorio usar el patrón de diseño MVC, donde las vistas son los formularios creados con Qt y los controladores serian los diálogos en donde se pone toda la funcionalidad.

En la carpeta form_ui, guardo los formularios sin que hayan sido compilados, solo para tener el resguardo de la última versión.

En la carpeta forms, pongo los formularios ya compilados.

En images pongo las imágenes que usare dentro de mi aplicación, tanto iconos usados en los botones, como imágenes de fondo, etc.

En la carpeta impresión suelo poner los códigos fuentes de los programas dedicados a realizar reportes en PDF que luego se imprimen desde el sistema.

Por ultimo en la carpeta útiles, pongo código genérico que puedo utilizar en varios programas, para aumentar la reusabildiad de código.



Veamos un ejemplo funcional de cómo se realizaría la escritura en una Base de datos sencilla.

Ya tenemos nuestro FormCargarPersona.py… Ahora creemos el resto de los archivos necesarios para hacer funcional nuestro programa.

#conexion.py

import sqlalchemy as sql
from PyQt4.QtGui import *
from sqlalchemy.orm import sessionmaker

class conexion():
   
    def __init__(self):
        self.my_db = sql.create_engine('sqlite:///personas')
        self.metadata  = sql.MetaData(self.my_db)
   
   
    def crearSession(self):
        Session = sessionmaker(bind=self.my_db)
        session = Session()
        return session

#creacionTablas.py

from sqlalchemy import Table, Column, Integer, String, MetaData, Sequence
from conexion import conexion
from sqlalchemy.orm import mapper

from Personas import Personas

class creacionTablas():
    def __init__(self):
        bd = conexion()
        metadata = MetaData()
        print 'Creacion de tablas'


        tabla_personas = Table('personas', metadata,
            Column('idPersona', Integer, Sequence('user_id_seq'), primary_key=True),
            Column('nombre', String(30)),
            Column('apellido', String(30)),
            Column('direccion', String(30))
        )

        metadata.create_all(bd.my_db)

        mapper(Personas,tabla_personas)





#Personas.py

class Personas(object):

    def __init__(self, nombre, apellido, direccion):
        self.nombre = nombre
        self.apellido = apellido
        self.direccion = direccion


#PrincipalPersona.py

import sys
import PyQt4
sys.path.append("..")

import creacionTablas
from PyQt4.QtGui import *
from PyQt4 import QtGui
from PyQt4 import QtCore

from dlgCargarPersonas import dlgCargarPersonas

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    creacionTablas.creacionTablas()
    d = dlgCargarPersonas()
    d.exec_()


#dlgCargarPersonas.py

from PyQt4 import QtCore, QtGui
from FormCargarPersona import Ui_FormCargarPersona
from Personas import Personas
import conexion
import PyQt4
import sys

class dlgCargarPersonas(QtGui.QDialog):

    def __init__(self):
        QtGui.QDialog.__init__(self)
        self.ui = Ui_FormCargarPersona()
        self.ui.setupUi(self)
        conect = conexion.conexion()
        self.session = conect.crearSession()
        self.connect(self.ui.btnAceptar, QtCore.SIGNAL("clicked()"), self.prueba)
       
    def cargarPersona(self):
        if(self.ui.txtApellido.text() <> "" and
           self.ui.txtNombre.text() <> ""):
            nombre = str(self.ui.txtNombre.text())
            apellido = str(self.ui.txtApellido.text())
            direccion = str(self.ui.txtDireccion.text())
            persona = Personas(nombre, apellido, direccion)
            self.session.add(persona)
            self.session.commit()
   
Poniendo estos 5 archivos en una misma carpeta y ejecutando PrincipalPersona.py, debería poderse guardar personar en la base de datos. Para ver si efectivamente se guardaron los datos en la base de datos podemos usar el sqliteman, que ya descargamos previamente, abrimos la base de datos que se llama personas, que se encontrara en la misma carpeta en donde tenemos todos los fuentes, y hacemos un Select * from personas. 

2 comentarios:

  1. muy buena gracias, pero me gustaria ver un video tutorial para que me quede mas claro, gracias.

    ResponderEliminar
  2. Luis, si lo que queres es hacer programas de escritorio con interfaces graficas, te recomiendo un "Framework" que hice, que podes descargalo y tenes un par de videos que te explican como se utiliza. Fijate en este post de mi blog.

    http://infortips.blogspot.com.ar/2012/11/framework-python.html

    Cualquier duda o consulta hacela sin problemas.

    Saludos

    ResponderEliminar