Fundamentos de POO para interfaces gráficas en Python

Primer programa con WxPython

Ahora que hemos visto Tkinter, las otras bibliotecas se entenderán mucho más fácilmente, ya que la estructura de los programas es prácticamente la misma cambiando un poco la sintaxis.

En esta lección vamos a conocer WxPython /wixpython/, un binding para WxWidgets /wixwidgets/, una biblioteca libre y multiplataforma para desarrollar interfaces en C++.

Cuenta con un conjunto de elementos gráficos mucho más extenso que el de Tkinter y a diferencia de éste es mucho más flexible para controlar la interfaz. Algunas características interesantes que ofrece son por ejemplo una apariencia más nativa en cada sistema operativo, la posibilidad de separar el diseño del código usando ficheros XML y también la de crear tus propios componentes gráficos. Por contra es más difícil de aprender y hay que instalarla a parte.

Así que empecemos por instalarla desde el prompt de Python o una CMD:

pip install wxpython

Ahora veamos como es aquí la estructura base de un programa:

hola_wx.py

import wx

# Creamos una nueva app
app = wx.App()

# Iniciamos el bucle
app.MainLoop()

Al ejecutar este código no ocurrirá nada, eso es porque la aplicación raíz no tiene componente gráfico, sirve para manejar el proceso.

Para crear una ventana instanciaremos un componente llamado Frame:

import wx

app = wx.App()

# Le añadimos un marco contenedor
frame = wx.Frame(None, wx.ID_ANY, "Hola mundo")

app.MainLoop()

Pero con esto aún no es suficiente, tenemos que mostrar ese Frame porque por defecto está escondido:

frame = wx.Frame(None, wx.ID_ANY, "Hola mundo")
frame.Show(True)

Para establecerle un tamaño distinto lo haremos con un argumento size:

frame = wx.Frame(None, wx.ID_ANY, "Hola mundo", size=(200, 100))

Esto ya empieza a funcionar, vamos a añadir un botón a la ventana:

button = wx.Button(frame, wx.ID_ANY, "Hola")

¡Perfecto! Ya sólo nos falta crear una función y llamarla al presionar el botón:

def hola(self):
    print("¡Hola mundo!")

# ...

button = wx.Button(frame, wx.ID_ANY, "Hola")

# Aquí conectamos la función al botón con el método Bind
button.Bind(wx.EVT_BUTTON, hola)

Listo, ya tenemos una versión estructurada del programa "Hola mundo, ahora vamos a trasladar esto a clases y objetos:

import wx


class MainWindow(wx.Frame):
    # Creamos nuestra ventana a partir de un Frame

    def __init__(self):
        # Con super ejecutamos su propio constructor y le pasamos los argumentos
        # Así se crea la ventana en su propia instancia self
        super().__init__(None, wx.ID_ANY, size=(200, 100))
        button = wx.Button(self, wx.ID_ANY, "Hola")
        button.Bind(wx.EVT_BUTTON, self.hola)
        # Finalmente mostramos la ventana
        self.Show(True)

    # Se requiere un parámetro de argumentos indeterminados en los métodos
    def hola(self, *args):
        print("¡Hola mundo!")


# Creamos la aplicación, la ventana e iniciamos el bucle
app = wx.App()
window = MainWindow()
app.MainLoop()

En esencia es casi lo mismo que la versión hecha con Tkinter, sólo que aquí como necesitamos utilizar obligatoriamente un Frame para hacer de contenedor podemos usarlo en nuestra propia clase.

Igual que antes os dejaré un par de enlaces con documentación en los apuntes: