El lenguaje de programación Python permite adoptar diversas librerías y framework para desarrollar interfaces gráficas. Algunas son Tinker, Wxwidget y QT, plataforma sobre la que vimos los tutoriales:
En este tutorial veremos como desarrollar interfaces gráficas con WxWidget y la herramienta de diseño wxFormBuilder. wxFormBuilder es una aplicación de diseño de interfaces gráficas de usuario, es libre y de código abierto permite utilizar la librerías wxWidgets, es muy utilizado para el desarrollo de aplicaciones multiplataforma.
wxFormBuilder es una herramienta de desarrollo visual, La gran ventaja es que puede generar código en C ++, Python, PHP, Lua y XRC mientras se va diseñando. Funciona en Windows, Linux y Mac Os.
Para estre tutorial haremos una instalación en Linux y en una máquina virtual con VirtualBox y Windows 7, para poder probar que podemos desarrollar la aplicación multiplataforma, de igual forma podríamos instalar en Linux y tener una maquina virtual con Linux.
Necesitaremos instalar las siguiente herramientas:
Una de las ventajas de Python es que soporta múltiples paradigmas de programación, como ser orientación a objetos, programación imperativa y funcional o procedimiento. Podemos descargar Python desde la web oficial.
Es una conjunto de librerías que permiten portar y utilizar la biblioteca gráfica wxWidgets utilizando el lenguaje de programación Python. La biblioteca wxWidgets se caracteriza por ser multiplataforma.
Se puede descargar desde la web oficial de WxPython, en Linux viene en los repositorios o se puede añadir
wxFormbuilder permite generar código en C ++, Python, PHP, Lua y el código XRC. El codigo se va creando a media que vamos diseñando.
Lo podemos descargar desde su pagina oficial, debemos instalar una versión superior a la 3.4 que es la que soportar todos los lenguajes mencionados anteriormente.
En este tutorial desarrollaremos la aplicación bajo linux y luego la ejecutaremos también en Windows. En Linux python ya viene instalado por lo que instalaremos wxPython y wxFormbuilder, desde una ventana de terminal escribimos los siguientes comando:
sudo add-apt-repository -y ppa:wxformbuilder/wxwidgets sudo apt-get update sudo apt-get install libwxgtk3.0-0 libwxgtk-media3.0-0 sudo add-apt-repository -y ppa:wxformbuilder/release sudo apt-get update sudo apt-get install wxformbuilderLuego debemos añadir wxpython como variable de entorno para poder utilizarlo desde cualquier directorio:
export PYTHONPATH="$PYTHONPATH":/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/A continuación abrimos wxFormbuilder desde el menú principal:
wxFormBuilder presenta un escritorio con una columna izquierda donde se ubicaran el proyecto o pantalla y componentes que vayamos utilizando, en el centro la pestaña de diseño y una pestaña por cada lenguaje, a la derecha tendremos las propiedades tanto del proyecto como de los componentes que utilicemos.
Lo primero que deberemos configurar sera el proyecto, para ello hacemos un clic en el nombre del proyecto y luego vamos a las propiedades donde asignaremos un nombre y el lenguaje que utilizaremos.
A continuación vamos a la pestaña Form y añadimos un formulario que sera el contenedor de la pantalla.
Luego desde las propiedades podremos modificar el nombre del formulario al que le asignamos MiForm y el titulo que será Ejemplo01- Tutorial, ademas podremos modificar muchas opciones como el color de fondo, el tamaño, el tipo de ventana y muchos mas.
Podemos ir a la pestaña Python y ver como se va generando el código.
Para generar el código en un archivo, primero deberemos guardar el proyecto desde el menú File > Save As, y lo guardamos como ejemplo01.fbp
A continuación vamos a la opción del menú File > Generate Code, luego vamos al directorio donde guardamos el archivo del proyecto y veremos el archivo noname.py
Este archivo noname.py contiene el código Python generado con el diseño de la interfaz, podemos renombrar el archivo a ejemplo01.py
A continuación debemos añadir el código para que se muestre este diseño cuando se ejecuta la aplicación.Para ello abrimos el archivo y añadimos el siguiente código debajo quedándonos de la siguiente manera:
import wx import wx.xrc class MiForm ( wx.Frame ): def __init__( self, parent ): wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Ejemplo01 - Tutorial ", pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL ) self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize ) self.Centre( wx.BOTH ) def __del__( self ): Pass #Fin código del diseño de Formulario ## Código que muestra la aplicación al ejecutarse app = wx.App(False) frame = MiForm (None) frame.Show(True) app.MainLoop()Luego desde una ventana de terminal vamos al directorio de la aplicación y ejecutamos python ejemplo01.py
A continuación vamos a wxFormbuilder y comenzaremos a diseñar la pantalla. Los componentes se distribuyen en la pantalla mediante Layout y grillas, en este caso seleccionaremos un wxBoxSizer vertical, lo que hace es dividir la pantalla en tres filas, donde añadiremos los componentes.
A continuación añadiremos un menú, para ello nos vamos a la pestaña Menu/Toolbar, primer añadiremos el componente MenuBar que sera el menú principal. Luego iremos añadiendo por jerarquía un Menutitem Abrir, un separador y otro Menuitem con el nombre Salir.
Podemos ver que los objetos se van acomodando según una jerarquía donde el de más arriba abarca a los de mas abajo, podemos intercambiarlos de posición con solo arrastrar. Luego iremos a la pestaña Data y añadiremos un control wxGrid para mostrar una grilla de datos, para ellos nos situamos en el Layout asi el próximo control se ubicara debajo del menú.
Generamos el nuevo código y se modificará el archivo noname.py, podemos renombrarlo como ejemplo02.py, añadiendo los cambio realizados. Luego ejecutamos desde una ventana de terminal mediante el comando:
python ejemplo02.py
A continuación vamos a wxFormbuilder y añadiremos una barra separadora debajo de la grilla, desde la pestaña Common y seleccionamos el componente wxStaticLine.
A continuación crearemos campos como para hacer un maestro detalle, para ello nos situaremos en el Layout y añadiremos un componente.
Además de diseñar interfaces gráficas podemos añadir eventos, por ejemplo hacemos clic en el botón grabar y vamos a la pestaña Events, buscamos el tipo de evento, en este caso OnLeftDown, clic del botón izquierdo del mouse presionado.
En este evento escribimos el nombre de la función que invocará el evento, al generar el código solo nos creara la función luego deberemos escribir el código con la funcionalidad. Cuando hayamos generado el archivo añadiremos al final el siguiente código completo:
import wx import wx.xrc import wx.grid ########################################################################### ## Class MyFrame1 ########################################################################### class MiForm ( wx.Frame ): def __init__( self, parent ): wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 417,350 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL ) self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize ) bSizer1 = wx.BoxSizer( wx.VERTICAL ) self.m_grid1 = wx.grid.Grid( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 ) # Grid self.m_grid1.CreateGrid( 4, 4 ) self.m_grid1.EnableEditing( True ) self.m_grid1.EnableGridLines( True ) self.m_grid1.EnableDragGridSize( False ) self.m_grid1.SetMargins( 0, 0 ) # Columns self.m_grid1.EnableDragColMove( False ) self.m_grid1.EnableDragColSize( True ) self.m_grid1.SetColLabelSize( 30 ) self.m_grid1.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE ) # Rows self.m_grid1.EnableDragRowSize( True ) self.m_grid1.SetRowLabelSize( 80 ) self.m_grid1.SetRowLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE ) # Label Appearance # Cell Defaults self.m_grid1.SetDefaultCellAlignment( wx.ALIGN_LEFT, wx.ALIGN_TOP ) bSizer1.Add( self.m_grid1, 0, wx.ALL, 5 ) self.m_staticline4 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) bSizer1.Add( self.m_staticline4, 0, wx.EXPAND |wx.ALL, 5 ) fgSizer1 = wx.FlexGridSizer( 0, 4, 0, 0 ) fgSizer1.SetFlexibleDirection( wx.BOTH ) fgSizer1.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) self.m_staticText1 = wx.StaticText( self, wx.ID_ANY, u"Producto", wx.DefaultPosition, wx.DefaultSize, 0 ) self.m_staticText1.Wrap( -1 ) fgSizer1.Add( self.m_staticText1, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) self.m_textCtrl1 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) fgSizer1.Add( self.m_textCtrl1, 1, wx.ALL|wx.EXPAND, 5 ) self.m_staticText2 = wx.StaticText( self, wx.ID_ANY, u"Código", wx.DefaultPosition, wx.DefaultSize, 0 ) self.m_staticText2.Wrap( -1 ) fgSizer1.Add( self.m_staticText2, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) self.m_textCtrl2 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) fgSizer1.Add( self.m_textCtrl2, 1, wx.EXPAND|wx.ALL|wx.ALIGN_BOTTOM, 5 ) self.m_staticText3 = wx.StaticText( self, wx.ID_ANY, u"Categoría", wx.DefaultPosition, wx.DefaultSize, 0 ) self.m_staticText3.Wrap( -1 ) fgSizer1.Add( self.m_staticText3, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) m_comboBox1Choices = [] self.m_comboBox1 = wx.ComboBox( self, wx.ID_ANY, u"Seleccionar", wx.DefaultPosition, wx.DefaultSize, m_comboBox1Choices, 0 ) fgSizer1.Add( self.m_comboBox1, 0, wx.ALL, 5 ) self.m_staticText4 = wx.StaticText( self, wx.ID_ANY, u"Fecha de ingreso", wx.DefaultPosition, wx.DefaultSize, 0 ) self.m_staticText4.Wrap( -1 ) fgSizer1.Add( self.m_staticText4, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5 ) self.m_datePicker1 = wx.DatePickerCtrl( self, wx.ID_ANY, wx.DefaultDateTime, wx.DefaultPosition, wx.DefaultSize, wx.DP_DEFAULT ) fgSizer1.Add( self.m_datePicker1, 1, wx.ALL|wx.EXPAND, 5 ) bSizer1.Add( fgSizer1, 1, wx.EXPAND|wx.ALL, 5 ) self.m_staticline3 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) bSizer1.Add( self.m_staticline3, 0, wx.EXPAND |wx.ALL, 5 ) bSizer2 = wx.BoxSizer( wx.HORIZONTAL ) bSizer2.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 ) self.m_button4 = wx.Button( self, wx.ID_ANY, u"Grabar", wx.DefaultPosition, wx.DefaultSize, 0 ) bSizer2.Add( self.m_button4, 0, wx.ALL, 5 ) self.m_button5 = wx.Button( self, wx.ID_ANY, u"Eliminar", wx.DefaultPosition, wx.DefaultSize, 0 ) bSizer2.Add( self.m_button5, 0, wx.ALL, 5 ) bSizer1.Add( bSizer2, 1, wx.EXPAND|wx.ALL, 5 ) self.SetSizer( bSizer1 ) self.Layout() self.m_menubar1 = wx.MenuBar( 0 ) self.m_menu1 = wx.Menu() self.m_menuItem1 = wx.MenuItem( self.m_menu1, wx.ID_ANY, u"Abrir", wx.EmptyString, wx.ITEM_NORMAL ) self.m_menu1.AppendItem( self.m_menuItem1 ) self.m_menu1.AppendSeparator() self.m_menuItem3 = wx.MenuItem( self.m_menu1, wx.ID_ANY, u"Salir", wx.EmptyString, wx.ITEM_NORMAL ) self.m_menu1.AppendItem( self.m_menuItem3 ) self.m_menubar1.Append( self.m_menu1, u"Archivos" ) self.SetMenuBar( self.m_menubar1 ) self.Centre( wx.BOTH ) # evento click que invoca a la funcion grabar self.m_button4.Bind( wx.EVT_LEFT_DOWN, self.Grabar ) def __del__( self ): pass # creamos un cuadro de dialogo o mensaje personalizado def Mensaje(self, msg, title, style): dlg = wx.MessageDialog(parent=None, message=msg, caption=title, style=style) dlg.ShowModal() dlg.Destroy() # Funcion grabar que responde al evento click def Grabar( self, event ): self.Mensaje("Esto es un evento click!", "Información - Tutorial", wx.OK|wx.ICON_INFORMATION) app = wx.App(False) frame = MiForm (None) frame.Show(True) app.MainLoop()
A continuación vamos a probar la misma aplicación en una instalación de Windows 7 con Python y wxpython instalados previamente y el resultado es el siguiente:
Cuando finalizamos nuestro desarrollo completo, se puede distribuir la aplicación utilizando un software como InnoSetup como habíamos visto en los tutoriales:
wxFormBuilder es un entorno visual nos da la brinda de generar código Python con la plataforma wxPython, otra alternativa para desarrollar interfaces gráficas para Python quedará a elección del usuario si usar PyQt o wxPython.
Una de las grandes ventajas de wxFormBuilder es que contiene muchos componentes y widgets, muy personalizables inclusive mas que en otros entornos mas conocidos. Podemos ver los resultados a medida que vamos creando la aplicaciones, así podemos tener distintas versiones de la interfaz gráfica y del codigo que vayamos añadiendo. A diferencia de Qt Designer wxFormBuilder permite generar los eventos para luego invocar una funcionalidad determinada.
.