Blog
Desarrolla tu GUI con wxPython en python 3
- Publicado por: Rafael Fernandez
- Categoría: Blog

wxPython es una adaptación de la biblioteca gráfica wxWidgets para ser usada en el lenguaje de programación Python y de esta forma facilitar el desarrollo de aplicaciones gráficas.
En el presenta articulo veremos de que se trata y como utilizarla. Pero antes aportaremos información sobre la biblioteca que le da razón de ser.
¿Qué es wxWidgets?
Para comenzar hemos de mencionar que las wxWidgets son bibliotecas multiplataformas y libres, creadas con el objetivo de desarrollar interfaces graficas como entornos de programación hechos en lenguaje C++.
Estas bibliotecas se caracterizan principalmente por su portabilidad y capacidad de operar en distintos sistemas operativos, como Windows, MacOS, GTK+, Motif, OpenVMS y OS/2.
Además, es posible utilizarlo en otros lenguajes además de C++; a saber, Java, JavaScript, Perl, Smalltalk, Ruby, Erlang y Python (wxpython Python 3).
Origen del wxWidgets
El origen de wxWidgets se remonta al año 1992. En ese año Julian Smart de la Universidad de Edinburgo diseñaba la herramienta metacase conocida como Hardy. No obstante, precisaba que corriera en sistemas operativos Window y X-Unix, para lo cual era necesario contar con herramientas multiplataforma que dentro del mercado tenían costos muy elevados.
Por lo tanto, en vista de la dificultad para obtenerlo decidió realizar uno propio, al que llamó inicialmente wxWindows; aunque luego tuvo que cambiar el nombre debido a una demanda otorgada por la empresa Microsoft a finales de 2013.
Ventajas de usar wxWidgets
La ventaja principal para usarla es que se trata de un framework bastante versátil. Entre otras cosas incluye clases que permiten manejar archivos y directorios de forma independiente del sistema y además cuenta con funcionalidades útiles como gráficos 2D y 3D, base de datos, visión e impresión del HTML.
Por otro lado, cuenta con soporte y suficiente documentación en internet como ayudas, foros, tutoriales y más; de manera que es accesible para todos y resulta fácil de aprender.
Y por último cabe resaltar su capacidad para trabajar con distintos lenguajes de programación, por ejemplo, Python.
Aprendamos a continuación específicamente sobre wxPython.
¿Cómo surgió wxPython?
Uno de los principales desarrolladores de este binding de wxWidgets es Robind Dunn.
En su momento, Dun necesitaba un GUI capaz de funcionar en sistema HP-UX se encontró unas adaptaciones de Python para el toolkit wxWidgets y por ello rápidamente aprendió Python para comenzar con el proyecto.
Al principio las versiones del wrapper se hicieron a mano, pero no podían mantenerlas sincronizadas con los releases de wxWidgets; sin embargo, tiempo después se crearon con el software desarrollador “SWIG” y gracias a esto se pudo reducir considerablemente la cantidad de trabajo que suponía hacer la actualización del wrapper.
Licencia
Dado que wxPython es un binding o adaptación del framework creado por Julian Smart, utiliza la misma licencia; a saber, software libre (LGPL), licencia aprobada por la Fundación del Software Libre y la Open Source Initiative.
El proyecto Phoenix
A partir de 2012 se puso en marcha el proyecto Phoenix y se logró compatibilizar wxPython con Python 3. El objetivo de esta implementación siempre ha sido mejorar la velocidad, el mantenimiento y su extensión.
Además, gracias a que envuelve la biblioteca wxWidgets, es posible proporcionar acceso a ciertas partes de la misma a fin de crear interfaz de usuario, exponiendo la API de wx. Esto a su vez permite ofrecer aplicaciones Python que cuenten con interfaces capaces de funcionar en distintas plataformas (Windows, Max y Unix) usando poco código.
Aplicación wxPython con Python 3
Lo que presentaremos a continuación es un ejemplo lo que podemos crear con wxPython con Python 3.
Haremos una ventana con dos botones. Cabe destacar que lo más común es utilizar un diseño orientado a objetos, como el que veremos a continuación:
import wx class MiFrame(wx.Frame): def __init__(self,*args,**kwargs): wx.Frame.__init__(self,*args,**kwargs) # Agregando botones self.button = wx.Button(self, -1, u"Botón A", size=(100,20), pos=(10,10)) self.button = wx.Button(self, -1, u"Botón B", size=(100,20), pos=(10,50)) # Conectando el evento de un botón self.Bind(wx.EVT_BUTTON, self.OnClick) # Mostrando la interfaz self.Show() def OnClick(self,event): print(u"Botón presionado: %s"%(event.EventObject.GetLabel())) if __name__ == "__main__": app = wx.App() fr = MiFrame(None, -1, "wxPython App", size=(300,200)) app.MainLoop()
Lo que acabamos de hacer es definir la clase MiFrame que como mencionamos antes hereda de wx.Frame.
Posteriormente, incluimos el método __init__ que en este caso lo hemos establecido como el constructor de la clase; aquí dentro llamamos entonces al método de la superclase __init__ a la cual le pasamos los argumentos obtenidos desde el constructor de la clase.
Cabe destacar que la sintaxis de Python indica que el parámetro “self” siempre será el primero entre los argumentos del método de la clase y la superclase, y que dentro del método se agregarán los controles y la conexión de eventos.
Luego, mediante el método OnEvent podemos realizar devoluciones de llamada o respuestas en eventos previamente registrados.
Y por último, como muestra el script, instanciamos un objeto de la clase antes definida (MiFrame), usando los argumentos comunes para un wx.Frame.
Resultado:
Aplicación que muestra mensaje
El siguiente es otro ejemplo que muestra un mensaje en pantalla al presionar el botón de la izquierda.
import wx class MyFrame(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title) self.listbox_1 = wx.ListBox(self, -1) self.button_1 = wx.Button(self, -1, u"Mostrar Mensaje") self.button_2 = wx.Button(self, -1, u"Cerrar") self.__do_layout() self.__set_properties() self.__set_event() def __do_layout(self): sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_2 = wx.BoxSizer(wx.HORIZONTAL) sizer_1.Add(self.listbox_1, 1, wx.EXPAND|wx.ALL, 5) sizer_2.Add(self.button_1, 0, wx.ALL, 5) sizer_2.Add(self.button_2, 0, wx.ALL, 5) sizer_1.Add(sizer_2, 0, wx.ALL, 5) self.SetSizer(sizer_1) self.Layout() def __set_properties(self): self.SetSize( (800, 600) ) self.button_1.SetBackgroundColour( wx.Colour(200, 255, 100) ) self.listbox_1.SetFont( wx.Font(24, wx.DEFAULT, wx.NORMAL, wx.NORMAL) ) def __set_event(self): self.Bind(wx.EVT_BUTTON, self.OnButton1, self.button_1) self.Bind(wx.EVT_BUTTON, self.OnButton2, self.button_2) def OnButton1(self, event): self.listbox_1.Append(u"Hola Mundo") event.Skip() def OnButton2(self, event): self.Close() event.Skip() app = wx.App(0) frame = MyFrame(None, -1, "Hola Mundo") frame.Show() app.MainLoop()