Вы находитесь на странице: 1из 5

Python DESARROLLO

QT4 trae a Python nuevas mejoras en la creacin de programas

DESARROLLO RPIDO!
Ha llegado el cliente y te lo ha dejado claro: necesita el programa para ayer. Ha surgido un problema enorme y es necesario resolverlo en tiempo rcord. La desesperacin se palpa en el ambiente y todos los ojos miran a tu persona. Devuelves una mirada de confianza y dices con tono tranquilo: No te preocupes, tengo un arma secreta para acabar con el problema. POR JOS MARA RUZ

Nedelcu Sorin, www.sxc.hu

lgunos deciden dejar la habitacin, otros prefieren quedarse a tus espaldas, nerviosos, con los brazos cruzados y la mirada fija en ti. El problema est claro: viene en camino un gran envo, probablemente llegue hoy, con una gran cantidad de productos que se deben controlar porque en unos das saldrn con destino a un cliente. La ltima vez se hizo todo el proceso con hojas de clculo, pero fue un desastre. Esta vez quieren estar preparados. Es necesario desarrollar una aplicacin y que funcione en menos de 2 horas. Qt4 es la mejor opcin.

PyQT es un proyecto maduro Posee un entorno de desarrollo rpido de interfaces profesional: designer Estas caractersticas hacen de Qt4 una librera perfecta para el desarrollo rpido de programas. Adems es una librera totalmente multiplataforma, podemos desarrollar una sola vez y ejecutar donde queramos.

ventanas como las que aparecen en la Figura 1. Designer sirve para crear ventanas, para lo que debemos crear en primer lugar una venta normal y corriente (llamada en ingls MainWindow), como la que apa-

Designer
Una de las ventajas de Qt4 (ver Recurso [1]) es su designer. Es una herramienta, curtida en desarrollos profesionales, que nos permite comenzar diseando el aspecto grfico de la aplicacin. Para ello slo tenemos que ejecutar el comando designer-qt4 y aparecer un programa compuesto por distintas

Qt4
Qt4 es la librera sobre la que se basa el escritorio KDE4. Con licencia GPL, es una alternativa perfecta para desarrollar software libre. Posee algunas ventajas envidiables: Es muy completa (incorpora cdigo de acceso a base de datos, tratamiento svg, generacin de PDF) Es integrada (slo necesitas QT, no cientos de minipaquetes)

Figura 1: Designer permite crear interfaces de aplicaciones rpidamente.

WWW.LINUX- MAGAZINE.ES

Nmero 43

55

DESARROLLO Python

Figura 2: Nuestro MainWindow vaca y sin widgets.

rece en la Figura 2. sta ser la venta con la que trabajaremos durante todo el art-

culo. Por defecto viene con un barra de estado y otra de men, con la que comenzaremos. Para ello hay que pulsar dos veces con el ratn sobre Type Here y escribir &Archivo. De esta forma habremos creado nuestro primer men. Dentro de este men introduciremos, de igual forma, la accin &Salir. El smbolo & delante de las palabras indica que queremos que Qt4 genere teclas rpidas para ellas. Por ejemplo, al poner un & delante de Archivo hacemos que su primera A sirva como tecla rpida, activando el men cuando pulsemos alt-a. El

resultado sera el que vemos en la Figura 3. Vamos a trabajar con datos, por lo que lo mejor que podemos hacer es emplear el widget Table View, que nos permite trabajar con datos tabulares y que podremos conectar, ms adelante, con nuestra base de datos de forma casi directa. Para ello tenemos que ir a la ventana principal de Designer y buscar en Item Views el widget Table View. Debemos arrastrarlo hasta la ventana, quedando algo parecido a lo que podemos ver en la Figura 4. Queda mal, no? Lo ideal sera que ocupase todo el

Listado 1: Nuestro programa


01 02 03 04 05 06 07 08 09 #!/usr/local/bin/python # -*- coding: utf-8 -*import sys from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import QtSql from gui import Ui_MainWindow 25 26 27 def generaModelo(self): self.conectaDB() modelo = QtSql.QSqlTableModel(None, self.db) 28 modelo.setTable(inventario) 29 modelo.setSort( self.recordPrototipo.indexOf( ean13), QtCore.Qt.AscendingOrder) 30 31 32 33 34 def conectaDB(self): self.db = QtSql.QSqlDatabase.addDatabase (QPSQL) 35 36 37 38 39 40 self.db.setHostName(rufus) self.db.setDatabaseName( inventario) self.db.setUserName( josemaria) self.db.setPassword() name = self.db.open() query = QtSql.QSqlQuery( select * from inventario,self.db) 41 42 43 44 self.ui.tabla.resizeColumnsToC ontents() 45 46 47 48 49 def nuevaLinea(self): fila = self.modelo.rowCount() self.modelo.insertRow(fila) self.reajusta() 68 69 70 def reajusta(self): self.recordPrototipo = query.record() 60 61 62 63 64 65 66 if __name__ == __main__: 67 app = QtGui.QApplication( sys.argv) myapp = Programa() myapp.show() sys.exit(app.exec_()) def refrescar(self): self.modelo.select() 59 QtGui.QMessageBox.Yes| QtGui.QMessageBox.No) == QtGui.QMessageBox.Yes: self.modelo.removeRow(fila) self.reajusta() 58 #%1, %2? ).arg(ean13).arg(nombre), 56 57 if QtGui.QMessageBox.question( self, Borrar linea, QtCore.QString( Desea borrar el producto modelo.select() return modelo 55 53 54 50 51 52 def eliminarLinea(self): index = self.ui.tabla.currentIndex() fila = index.row() ean13 = self.modelo.data(self.modelo.i ndex(fila, self.recordPrototipo.indexOf( ean13))).toString() nombre = self.modelo.data(self.modelo.i ndex(fila, self.recordPrototipo.indexOf( nombre))).toString()

class Programa(QtGui.QMainWindow): 10 def __init__(self, parent=None): 11 QtGui.QWidget.__init__(self, parent) 12 13 self.modelo = self.generaModelo() 14 15 self.ui = Ui_MainWindow() 16 self.ui.setupUi(self) 17 self.ui.tabla.setModel(self.mo delo) 18 self.reajusta() 19 20 QtCore.QObject.connect( self.ui.action_Salir,QtCore.SI GNAL(activated()),QtGui.qApp , QtCore.SLOT(quit()) ) 21 QtCore.QObject.connect( self.ui.refrescar,QtCore.SIGNA L(clicked()),self.refrescar ) 22 QtCore.QObject.connect( self.ui.nuevaLinea,QtCore.SIGN AL(clicked()),self.nuevaLine a ) 23 QtCore.QObject.connect( self.ui.eliminarLinea,QtCore.S IGNAL(clicked()),self.elimin arLinea ) 24

56

Nmero 43

WWW.LINUX- MAGAZINE.ES

Python DESARROLLO

Figura 3: Nuestro men, esperando las opciones.

espacio visible, para lo cual tenemos que asignar un Layout (disposicin) al espacio en el que pondremos nuestro Table View. Hay que pulsar con el botn derecho sobre el espacio gris que rodea al Table View, ver Figura 5, y pulsar en la ltima opcin del men: Lay out. En ella escogeremos Lay out Vertically y nuestro Table View ocupar todo el espacio. Pulsamos dos veces con el ratn sobre el Table View y aparecer una ventana que nos permitir cambiar su nombre. Esto es muy importante, ya que posteriormente nos referiremos a Table View por este nombre, por lo que lo bautizaremos con uno que sea claro y conciso (aunque no muy imaginativo): tabla. Nuestra tabla, tal como aparece aqu, nos permitira ver datos, incluso editarlos, pero no aadir ni tampoco borrar. Para ello necesitamos botones que inicien acciones externas. Emplearemos Tool Buttons que nos permiten utilizar imgenes en su interior. Estos botones los solemos ver en las aplicaciones justamente debajo del men. Dispondremos 3 de estos botones: uno para refrescar los datos, uno para aadir y otro para borrar. El botn de refresco es muy importante, puesto que al trabajar varias personas a la vez en la base de datos puede darse el caso de que necesitemos saber si se ha introducido ya algn dato en particular. Estos 3 botones los situaremos entre el men y la tabla, quedando como puede apreciarse en la Figura 6. Pero, por qu aparecen as? No sera mejor que apareciesen a lo ancho? S, lo sera, pero hemos indicado a designer que disponga los widgets verticalmente. La solucin consiste en indicarle ahora que los disponga horizontalmente, para lo cual slo tenemos que seleccionarlos con el ratn (como si fueran ficheros, enmarcndolos en un cuadrado de seleccin), pulsar el botn derecho sobre ellos y en Lay outs seleccionar Break

LayOut. Con esta accin deshacemos la disposicin que elegimos anteriormente, pero para rehacerla, volvemos a pulsar el botn derecho y para estos tres botones seleccionados elegimos Lay out Horizontally, dejndolos como aparecen el Figura 7. Volvemos a pulsar con el botn derecho, aunque ahora sobre el rea gris entre los botones y el Table View, y seleccionamos Lay Out Vertically, quedando todos los widgets como en la Figura 8, Figura 4: Table View descolocado hacia el lado izquierdo. con lo que prcticamente hemos acabado con el diseo de la interfaz. que vaya a necesitar nuestra aplicacin, lo Nos quedan unos retoques. que simplifica la instalacin. La segunda A los botones hay que darles nombre. opcin, ms simple, nos permite indicar el Para hacerlo slo tenemos que pulsar el nombre del fichero que emplearemos. Utibotn derecho sobre ellos y elegir Change lizaremos la segunda opcin, Choose objectName. Los llamaremos, respectivaFile..., por ser ms simple. Seleccionamos mente: refrescar,nuevaLinea, elimiun fichero grfico con el icono, y hacemos narLinea. El ltimo retoque consiste en lo mismo para los otros botones, ver Figura asignarles unos iconos, de forma que sean 9. identificables visualmente. Para esto lo Cuando guardemos nuestro diseo mejor es darse un paseo por los directorios generaremos un fichero con extensin .ui de iconos de Gnome o Kde y seleccionar (User Interface), que llamaremos gui.ui. los ms acordes. Los copiamos a nuestro Este fichero describe la interfaz grfica que directorio de desarrollo, y en designer pulhemos diseado, aunque no lo podemos samos la combinacin de teclas control-i. emplear directamente, sino que hay que Aparecer el Property Editor que nos percompilarlo. Para ello empleamos el promite cambiar los parmetros de los widgrama pyuic4: gets. Estamos interesados en los de los botones, por lo que slo tenemos que josemaria@rufus> pyuic4U seleccionar un botn para que el Property gui.ui > gui.py Editor cambie para mostrar los parmetros de ese botn. Vamos a cambiar el parmetro Icon, que est en la seccin QAbstractButton. Si pulsamos en l veremos que a la derecha hay un botn que nos permite seleccionar entre Choose Resource y Choose File.... La primera opcin sirve para guardar en un solo fichero, llamado de recursos, Figura 5: El men Lay out nos permite colocar correctamente los eletodos los ficheros mentos.

WWW.LINUX- MAGAZINE.ES

Nmero 43

57

DESARROLLO Python

El resultado de compilar este fichero es la generacin de un fichero Python que realiza todo lo necesario para que tengamos nuestra interfaz grfica funcionando. Ahora necesitamos crear un programa que, usando este fichero como librera, gestione la aplicacin que estamos creando. Miramos nuestro reloj, slo han pasado 15 minutos, nuestros compaeros miran por encima de nuestro hombro tranquilos. Pero sabemos que este interfaz necesita de un cerebro para controlarlo, por el momento es slo una fachada.

La Base de Datos
Usaremos una base de datos remota Postgresql para almacenar los datos, de esta forma varias personas podrn trabajar a la vez en el programa. En lugar de emplear las libreras que existen para trabajar con Postgresql en Python usaremos Qt4. La tabla que crearemos ser tambin sencilla:
create table inventario ( ean13 char(13) primary key, nombre varchar not null, cantidad int not nullU default 0, constraintU inventario_cantidad_positivoU check(cantidad >= 0) )

Figura 6: Creamos tres nuevos botones

Qt4 trae consigo una librera de control de base de datos muy avanzada: QtSql. No se restringe a mandar cdigo sql, adems interacta directamente con los widgets de Qt usando un patrn de diseo denominado MVC (modelo vista controlador). Esta tcnica consiste en separar el cdigo de manipulacin de los datos, el cdigo que los muestra y el que toma las decisiones. Qt provee dos clases diferentes, una que representa los datos (el modelo) y otra que representa la visualizacin de los mismo (el visualizador), dejando el control de la aplicacin en nuestras manos. El modelo es una entidad autnoma e independiente, no requiere de la existencia de una base de datos. Podemos crear un modelo con tablas y filas, con relaciones y llaves, tal como si tuvisemos una base de datos. La razn detrs de este diseo es la de unificar la manipulacin de los datos en toda la aplicacin, estandarizndola. Las aplicaciones empresariales siempre tienen que interactuar con una base de datos, por lo que esta decisin de diseo es cada vez ms comn. Por tanto, podemos crear nuestro modelo de forma independiente, pero lo mejor no es eso. Lo realmente interesante es que podemos conectar ese modelo con una base de datos y seguiremos manipulando los datos empleando slo el modelo. Esto quiere decir que no tendremos apenas que escribir cdigo SQL, el modelo se encargar de ello por nosotros. Nuestra aplicacin estar totalmente desligada de la forma en la que se representan los datos. Hoy pueden estar en Postgresql, maana en MySQL y pasado en un fichero XML, y no tendremos que cambiar apenas el cdigo. Cmo se hace todo esto? Veamos el cdigo del Listado [1]. El mtodo conectaDB() muestra cmo realizar la conexin la base de datos Postgresql. El cdigo de Qt4 es sorprendentemente simple, comparado con otras libreras. Las ltimas dos lneas de cdigo son algo extraas.
query = QtSql.QSqlQueryU (select * from inventario,U

self.db) self.recordPrototipo =U query.record()

La primera de ellas realiza un select sobre la tabla inventario, lo que no es muy extrao, pero la segunda lnea emplea el resultado del select para generar un prototipo. Hacemos esto porque necesitamos saber el formato de una fila de la tabla inventario, para saber el nombre de las columnas y sus posiciones. Qt denomina a esta informacin Record y nos permitir realizar consultas posteriormente. El mtodo generaModelo() es ms interesante. Una vez realizada la conexin a la base de datos necesitamos generar un modelo de la tabla. Todos los modelos descienden de una clase comn, de forma que son intercambiables. Existen dos modelos de base de datos: QSqlTableModel, ms sencillo, y QSqlRelationalTableModel, que almacena tambin informacin sobre las relaciones entre distintas tablas. Nos conformamos con QSqlTableModel, puesto que nuestra tabla no est relacionada con otras. Una vez tenemos el modelo, seleccionamos la tabla que queremos manipular con setTable(). Es muy interesante que los productos que aparezcan en el Table View aparezcan ordenados por EAN-13, lo que facilitar bsquedas y comprobaciones a los usuarios. Para ello ordenamos el modelo con el mtodo setSort(). Acepta dos parmetros, la posicin de la columna que se emplear para ordenar y el tipo de ordenacin. Aqu entra en juego el prototipo que generamos antes de las filas de la tabla, que posee el mtodo indexOf() que nos devolver la posicin de una columna dada. La ordenacin puede ser QtCore.Qt.AscendingOrder (la primera fila tiene el valor ms bajo y la siguiente uno ms alto) o QtCore.Qt.DescendingOrder (lo contrario). Con el modelo listo pasamos a cargarlo con los datos, paso que realizamos invo-

Figura 7: Y los alineamos a nuestro gusto.

Figura 8: sta ser la disposicin final de los botones y tabla.

58

Nmero 43

WWW.LINUX- MAGAZINE.ES

Python DESARROLLO

poseen una serie de slots o conectores a los que pueden llegar seales. Estos slots realizan acciones cuando una seal los dispara. As, cuando se hace click sobre un botn, la seal clicked() se pasa a un slot por defecto del botn. Si queremos que el botn realice una accin diferente, podemos definir una coneFigura 9: Escogemos iconos representativos de las xin de clicked() con una acciones. funcin o mtodo que realice la accin que deseamos. En cando select(), que realiza un select sobre C++ este proceso requera de la Figura 10: Nuestra aplicacin en funcionamiento. la tabla, y almacenando los datos en el compilacin del cdigo fuente con modelo. un compilador de TrollTech, llamado moc, Nuestros compaeros se levantan para Volvemos a mirar nuestro reloj, han y posteriormente la compilacin con un ver qu estamos haciendo y casi dan un pasado 40 minutos. Nuestros compaeros compilador de C++. salto cuando observan que la aplicacin se ponen nerviosos, no ven ningn En Python todo es ms simple, slo est modificando la base de datos en avance. tenemos que emplear el mtodo tiempo real y de forma correcta. Nos QtCore.QObject.connect() para especificar miran y, con cara de emocin, nos espeConectando Mundos el widget y la seal que emite con el tan: Menos mal! creamos que todo Tenemos que vincular nuestro cdigo con mtodo que la gestionar. iba fatal, como no hicistes nada til la librera gui.py que generamos antes. En nuestro diseo tenemos 3 botones, durante la ltima media hora. As de Para ello la importamos: uno para refrescar, otro para aadir lneas sufrida es la programacin. Volvemos a y otro para borrarlas. Por tanto, tenemos mirar el reloj, todo listo en menos de from gui import Ui_MainWindow que conectar la seal clicked() de estos una hora. botones a mtodos que realicen estas Ahora, con ms tranquilidad nos disy generamos un objeto de tipo Ui_Mainacciones. ponemos a hacer de la aplicacin algo Window al que nos conectamos mediante La primera de ellas, refrescar, es la ms ms potente y a bautizarla! el mtodo setupUi(), ya que es nuestro simple. Slo tenemos que decirles al Conclusin programa quien lleva la batuta. Pasamos a modelo que vuelva a hacer un select() para tabla nuestro modelo de datos, de forma recargarse. En muy pocas lneas de cdigo, y gracias al que modelo y vista tambin se contactan. La segunda, nuevaLinea(), invoca al programa designer de Qt4, tenemos una A partir de ahora lo que haya en la base de mtodo insertRow() del modelo para crear aplicacin multiusuario funcional que datos se corresponder con lo que se vea una lnea vaca en el Table View. Cuando interacta con una base de datos. Qt4 ha en el Table View. El mtodo reajusta() se rellenen todos los campos de esta linea dejado el listn muy alto para el resto de hace que el Table View ajuste el ancho de se guardar automticamente en la base de frameworks de desarrollo. En particular, es sus columnas para que se puedan ver datos; el modelo se encarga de todo. interesante su total integracin con Wintodos los datos. En caso contrario har que La tercera accin, eliminarLinea(), locadows, MacOsX y Linux, permitindonos las columnas sean todas del mismo liza la posicin actual en la tabla obtehacer uso de nuestro software libre en tamao y algunos datos aparecern incomniendo el ndice de la celda que tenga el cualquiera de las tres plataformas de forma pletos. foco, y a partir de l obtiene la fila en la directa. Qt posee un sistema propio de prograque se encuentra. Por seguridad no borraQt4 es, sin duda, un opcin realmente macin denominado Seales y Slots. Qt remos directamente, sino que presentareinteresante para prototipado de aplicaciose desarroll en el lenguaje de programamos un cuadro de dilogo preguntando al nes o para desarrollo rpido, bajo presin. cin C++ y pronto se dieron cuenta de usuario si desea borrar la fila, mostrando Al fin y al cabo ha hecho que nuestro proI las deficiencias que posea. En particular, tanto el EAN-13 como el nombre del protagonista se convierta en un hroe. se dieron de bruces con la dificultad de la ducto. Para obtener ambos volvemos a programacin de eventos en C++. Como hacer uso del prototipo para conseguir sus RECURSOS resultado de estos problemas, TrollTech, la posiciones dentro de la fila y poder recupe[1] Qu es PyQt?: http://www. empresa creadora de Qt, decidi crear un rar sus valores. Una vez confirmada la eliriverbankcomputing.co.uk/software/ compilador y una serie de instrucciones minacin slo tenemos que emplear el pyqt/intro que hicieran la programacin de interfaces mtodo removeRow() del modelo. [2] Listado de clases con sus explicagrficas ms simple. Los detalles no son Poco ms es necesario para que nuestra ciones y ejemplos: http://www. importantes, al fin y al cabo este artculo es aplicacin sea funcional, el resultado final riverbankcomputing.co.uk/static/ sobre Python, pero el nuevo modelo de trapuede verse en funcionamiento en la Docs/PyQt4/html/classes.html bajo se basa en eventos. Los objetos de Qt Figura 10.

WWW.LINUX- MAGAZINE.ES

Nmero 43

59

Вам также может понравиться