Creación de aplicaciones GUI de Python con wxPython

C

Introducción

En este tutorial, aprenderemos a usar wxPython biblioteca para desarrollar interfaces gráficas de usuario (GUI) para aplicaciones de escritorio en Python. La GUI es la parte de su aplicación que permite al usuario interactuar con su aplicación sin tener que escribir comandos, puede hacer prácticamente todo con un clic del mouse.

Algunas de las alternativas populares de Python para desarrollar una GUI incluyen Tkintery pyqt. Sin embargo, en este tutorial, aprenderemos sobre wxPython.

Antes de seguir adelante, existen algunos requisitos previos para este tutorial. Debe tener un conocimiento básico de la sintaxis de Python y / o haber realizado al menos programación de nivel principiante en algún otro idioma. Aunque puede seguirlo, incluso si no cumple con estos criterios, es posible que algunas partes sean un poco complejas. Si es así, no dude en pedir aclaraciones en los comentarios.

Instalación

El proceso de instalación de wxPython es bastante sencillo, aunque difiere ligeramente según el sistema que esté utilizando.

Mac y Windows

WxPython es bastante fácil de instalar en Mac y Windows usando pepita gerente de empaquetación. Si tiene pip instalado en su sistema, ejecute el siguiente comando para descargar e instalar wxPython:

$ pip install wxpython

Linux

Para Linux, el procedimiento podría ser un poco complicado, ya que tiene muchas bibliotecas de requisitos previos que deben instalarse. Recomendaría intentar ejecutar los siguientes dos comandos en una secuencia:

# Command 1
$ sudo apt-get install dpkg-dev build-essential python2.7-dev python3.5-dev python3.6-dev libgstreamer-plugins-base1.0-dev libnotify-dev libwebkitgtk-3.0-dev libwebkit-dev libwebkitgtk-dev libjpeg-dev libtiff-dev libgtk2.0-dev libsdl1.2-dev libgstreamer-plugins-base0.10-dev freeglut3 freeglut3-dev

# Command 2
$ pip install --upgrade --pre -f https://wxpython.org/Phoenix/snapshot-builds/ wxPython

Sin embargo, si estos no funcionan, tendrá que instalar manualmente estas bibliotecas, una lista de las cuales se menciona en la sección “Requisitos previos” de WxPython Repositorio de Github.

Ejemplos de creación de GUI con wxPython

En esta sección, nos ensuciaremos las manos con wxPython y crearemos una aplicación básica de manipulación de cadenas con algunas funcionalidades básicas, como contar el número de palabras, mostrar la frecuencia de cada palabra, palabra más repetida, etc.

Antes de seguir adelante, crearemos una aplicación esqueleto muy simple, que usaremos como punto de partida en los próximos ejemplos para implementar funcionalidades GUI más avanzadas.

Sin más preámbulos, comencemos. A continuación se muestra el esqueleto o la estructura básica de una aplicación GUI construida con wxPython. Lo cambiaremos más en la siguiente sección para que esté orientado a objetos para una funcionalidad adicional.

import wx

# Creates an App object which runs a loop to display the
# GUI on the screen
myapp = wx.App()

# Initialises a frame that the user would be able to
# interact with
init_frame = wx.Frame(parent=None, title="Word Play")

# Display the initialised frame on screen
init_frame.Show()

# Run a loop on the app object
myapp.MainLoop()

Si el bucle no se ejecuta (es decir, el app.MainLoop() llamada), el marco aparecerá en la pantalla durante una fracción de segundo, e incluso antes de que pueda verlo, desaparecerá. Esta función asegura que el marco permanece visible en la pantalla, hasta que el usuario sale del programa, y ​​lo hace ejecutando el marco en un bucle.

Nota: Mientras ejecutaba esto en una Mac, recibí el siguiente error cuando ejecuté mi código usando python filename.py comando en la terminal:

This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.

Para deshacerse de esto, simplemente use pythonw en vez de python en el comando anterior.

Una vez que se ejecuta el programa, debería ver la siguiente ventana en blanco en su pantalla:

Código orientado a objetos

Antes de agregar funcionalidad a nuestro código, primero modularémoslo creando clases y funciones, para que se vea más limpio y sea más fácil extenderlo. La funcionalidad del siguiente código es la misma que antes, sin embargo, se ha refactorizado para implementar conceptos de programación orientada a objetos.

import wx
import operator

# We make a class for frame, so that each time we
# create a new frame, we can simply create a new
# object for it

class WordPlay(wx.Frame):
    def __init__(self, parent, title):
        super(WordPlay, self).__init__(parent, title=title)
        self.Show()

def main():
    myapp = wx.App()
    WordPlay(None, title="Word Play")
    myapp.MainLoop()

main()

En el script de arriba, creamos una clase WordPlay que hereda el wxFrame clase. El constructor del WordPlay la clase acepta dos parámetros: parent y title. Dentro del constructor hijo, el constructor de la clase padre para el wxPython se llama la clase y el parent y title se le pasan atributos. Finalmente, el show se llama al método para mostrar el marco. En el main() método, el objeto de WordPlay se crea la clase.

El código ahora parece mucho más estructurado y limpio; es más fácil de entender y se pueden agregar más funcionalidades al código anterior.

Añadiendo funcionalidades

Agregaremos funcionalidades una a la vez para evitar confusiones sobre qué parte del código se agrega para qué funcionalidad en particular. Lo que queremos en nuestra aplicación básica es un cuadro de texto donde podamos agregar texto, y luego unos botones para realizar diferentes funciones en ese texto, como calcular el número de palabras que contiene, la frecuencia de cada palabra, etc., seguido del la salida se muestra en la pantalla de nuestra aplicación.

Comencemos agregando un cuadro de texto a nuestra aplicación en el que podemos agregar nuestro texto.

# Some of the code will be the same as the one above,
# so make sure that you understand that before moving
# to this part

import wx
import operator

# We make a class for frame, so that each time we create a new frame,
# we can simply create a new object for it

class WordPlay(wx.Frame):
    def __init__(self, parent, title):
        super(WordPlay, self).__init__(parent, title=title)
        self.widgets()
        self.Show()

    # Declare a function to add new buttons, icons, etc. to our app
    def widgets(self):
        text_box = wx.BoxSizer(wx.VERTICAL) # Vertical orientation

        self.textbox = wx.TextCtrl(self, style=wx.TE_RIGHT)
        text_box.Add(self.textbox, flag=wx.EXPAND | wx.TOP | wx.BOTTOM, border=5)

        grid = wx.GridSizer(5, 5, 10, 10) # Rows, columns, vertical gap, horizontal gap
        text_box.Add(grid, proportion=2, flag=wx.EXPAND)

        self.SetSizer(text_box)

def main():
    myapp = wx.App()
    WordPlay(None, title="Word Play")
    myapp.MainLoop()

main()

Como puede ver, hemos agregado una nueva función llamada widgets() arriba, y ha sido llamado en el WordPlay constructor de la clase. Su propósito es agregar nuevos widgets a nuestra pantalla; sin embargo, en nuestro caso solo nos interesa agregar un widget, es decir, un cuadro de texto donde podemos agregar algo de texto.

Ahora entendamos algunas cosas importantes que están sucediendo dentro de este widgets() función. los BoxSizer() El método, como su nombre indica, controla el tamaño de los widgets, así como su posición (relativa o absoluta). los wx.VERTICAL especifica que queremos una orientación vertical para este widget. TextCtrl básicamente agrega un pequeño cuadro de texto en nuestro actual desde, donde el usuario puede ingresar una entrada de texto. los GridSizer() El método nos ayuda a crear una estructura similar a una tabla para nuestra ventana.

Muy bien, veamos cómo se ve nuestra aplicación ahora.

Ahora se puede ver un cuadro de texto en la ventana de nuestra aplicación.

Avancemos más y agreguemos dos botones a nuestra aplicación, uno para contar la cantidad de palabras en el texto y el segundo para mostrar la palabra más repetida. Lo lograremos en dos pasos, primero agregaremos dos botones nuevos y luego agregaremos controladores de eventos a nuestro programa que nos dirán en qué botón ha hecho clic el usuario, junto con el texto ingresado en el cuadro de texto, de modo que un Se puede realizar una acción específica en la entrada.

Agregar botones es bastante simple, solo requiere agregar un código adicional a nuestra función “widgets”. En el bloque de código a continuación, solo mostraremos la función de widgets actualizada; el resto del código permanece igual.

# Adding buttons to our main window

def widgets(self):
    text_box = wx.BoxSizer(wx.VERTICAL)

    self.textbox = wx.TextCtrl(self, style=wx.TE_RIGHT)
    text_box.Add(self.textbox, flag=wx.EXPAND | wx.TOP | wx.BOTTOM, border=5)

    grid = wx.GridSizer(2, 5, 5) # Values have changed to make adjustments to button positions
    button_list = ['Count Words', 'Most Repeated Word'] # List of button labels

    for lab in button_list:
        button = wx.Button(self, -1, lab) # Initialise a button object
        grid.Add(button, 0, wx.EXPAND) # Add a new button to the grid with the label from button_list

    text_box.Add(grid, proportion=2, flag=wx.EXPAND)

    self.SetSizer(text_box)

Como puede ver, ahora también se han agregado dos nuevos botones a nuestra ventana principal.

Agregar un controlador de eventos

La interfaz de nuestra aplicación ya está lista, todo lo que tenemos que hacer ahora es agregar controladores de eventos para realizar acciones específicas al hacer clic en los botones. Para eso tendremos que crear una nueva función y agregar una línea adicional de código en la función de widgets. Comencemos escribiendo nuestra función.

# Declare an event handler function

def event_handler(self, event):
    # Get label of the button clicked
    btn_label = event.GetEventObject().GetLabel()

    # Get the text entered by user
    text_entered = self.textbox.GetValue()

    # Split the sentence into words
    words_list = text_entered.split()

    # Perform different actions based on different button clicks
    if btn_label == "Count Words":
        result = len(words_list)
    elif btn_label == "Most Repeated Word":
        # Declare an empty dictionary to store all words and
        # the number of times they occur in the text
        word_dict = {}

        for word in words_list:
            # Track count of each word in our dict
            if word in word_dict:
                word_dict[word] += 1
            else:
                word_dict[word] = 1

            # Sort the dict in descending order so that the
            # most repeated word is at the top
            sorted_dict = sorted(word_dict.items(),
                                key=operator.itemgetter(1),
                                reverse=True)

            # First value in the dict would be the most repeated word
            result = sorted_dict[0]

    # Set the value of the text box as the result of our computation
    self.textbox.SetValue(str(result))

La lógica detrás de la función “Palabra más repetida” es que primero ejecutamos un ciclo que recorre la palabra de la lista de todas las palabras. Luego verifica si esa palabra en particular ya existe en el diccionario o no; si lo hace, significa que se está repitiendo y su valor se incrementa en uno cada vez que reaparece la palabra. De lo contrario, si no existe en el diccionario, significa que ha aparecido en la oración por primera vez y su valor de ‘ocurrencia’ debe establecerse en 1. Por último, ordenamos el diccionario (similar a la clasificación de listas de Python ) en orden descendente para que la palabra con el valor más alto (frecuencia) salga en la parte superior, que luego podemos mostrar.

Muy bien, ahora que hemos escrito el cálculo / acción que debe realizarse cuando se hace clic en un botón específico, “vinculemos” esa acción a ese botón en particular. Para eso, tendremos que modificar ligeramente nuestro widgets función.

# Only one line needs to be added in the "for loop" of
# our widgets function, so that's all we're showing
for lab in button_list:
    button = wx.Button(self, -1, lab)
    self.Bind(wx.EVT_BUTTON, self.event_handler, button)
    grid.Add(button, 0, wx.EXPAND)

En el código anterior, el self.Bind La llamada es donde ocurre el enlace. Lo que hace es que vincula una acción en particular a un botón específico, de modo que cuando hace clic en ese botón, se realiza una acción específica vinculada a él. En nuestro caso particular, solo tenemos una función de controlador de eventos, que maneja ambas acciones al verificar en tiempo de ejecución en qué botón se hizo clic a través de la propiedad ‘etiqueta’ y luego realizar la acción vinculada. Entonces en el self.Bind call vinculamos todos nuestros botones a la única función ‘event_handler’.

Muy bien, nuestro código ahora está completo. Probemos nuestras dos funciones y veamos si todo funciona como se esperaba.

En el primer paso, como se muestra a continuación, ingresamos una cadena en el cuadro de texto:

A continuación, si hacemos clic en el botón “Contar palabras”, debería ver “7” en el cuadro de texto, ya que había 7 palabras en la cadena.

¡Hasta aquí todo bien!

Ahora escribamos otra cadena en el cuadro de texto, como se muestra en la siguiente figura:

Ahora, si hacemos clic en el botón “Palabra más repetida”, verá las palabras más repetidas en el cuadro de texto, junto con su frecuencia de aparición, como se muestra a continuación:

¡Funciona perfectamente!

Solo hemos agregado dos funciones, pero el propósito era mostrarle cómo están conectados todos estos componentes, puede agregar tantas funcionalidades como desee simplemente escribiendo funciones adicionales para ellos. Además, este tutorial no se centró mucho en la estética. Hay muchos widgets disponibles en wxPython para embellecer su programa ahora que ha adquirido los conocimientos básicos del kit de herramientas.

Conclusión

Para resumir, aprendimos que wxPython se usa popularmente para desarrollar aplicaciones de escritorio basadas en GUI en Python, y que Python también tiene otras alternativas interesantes para ello. Revisamos los comandos para descargarlo e instalarlo en todos los sistemas operativos populares. Por último, aprendimos cómo hacer una aplicación modular usando wxPython que se puede extender fácilmente, como se puede ver en este tutorial donde construimos una aplicación básica de esqueleto y agregamos más funciones paso a paso.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con tus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad