Saltar al contenido
No vuelvas a olvidarte de la sintaxis de Python y acelera tu programación con la Hoja de Referencia, tu cheat sheet de Python en español.

Cómo Hacer un Menú en Python

Cómo hacer un menú en Python

Cuando hablamos de interfaces de usuario, uno de los artefactos que solemos necesitar a menudo en nuestras aplicaciones son los menús de opciones. En esta entrada te enseño diferentes maneras de crear un menú de usuario en Python, bien sea en modo texto, bien sea en modo gráfico.

Para crear un menú de usuario en Python en modo texto podemos mostrar las opciones al usuario e invocar las acciones correspondientes almacenadas en un diccionario. Si necesitamos un menú en tkinter debemos usar la clase Menu. Si lo queremos realizar en PyQt utilizaremos las clases QMenu y QAction.

Tras estas breves pistas que acabo de darte, voy a pasar a detallar a continuación estas tres opciones, que son las de hacer un menú en modo texto, utilizando la librería tkinter si necesitas una aplicación Tcl/Tk y utilizando PyQt5 si lo que necesitas es una aplicación Qt. ¡Quédate hasta el final!

Cómo hacer un menú en modo texto en Python

Para hacer un menú de usuario en Python en modo texto se muestran las opciones al usuario y se le solicita que elija una. Después se ejecuta la acción asociada a la opción elegida y se vuelve a mostrar el menú al usuario en bucle hasta que se selecciona la opción de terminar o salir.

Vamos a detallar esto que, aunque es sencillo, tiene algo de miga si lo queremos hacer bien. Antes de empezar a implementar, como siempre, tenemos, que pensar un poco. A la hora de hacer un menú tenemos que considerar tres elementos claramente diferenciados:

  • Las opciones que se le darán al usuario.
  • Las acciones que se ejecutarán y que están asociadas a cada una de las opciones.
  • La lógica del menú.

Es importante mantener una separación entre todas ellas, ya que, por ejemplo, una única acción podría estar asociada a varias opciones del menú. Además, con independencia de las opciones que se ofrezcan al usuario y de las acciones a ejecutar, un menú siempre tiene que funcionar de la misma manera (se muestran las opciones la usuario, se deja elegir una opción al usuario, se ejecuta la acción asociada a la opción elegida y se vuelve a mostrar el menú).

Creando las opciones del menú y asociándoles acciones

Vamos a empezar pensando en los dos primeros puntos. Para resolver esta parte vamos a utilizar un diccionario de manera muy similar a como se hace en otro artículo donde te explico el patrón de diseño comando (o command).

Para terminar de clarificar lo que queremos conseguir, imaginemos que lo que pretendemos es hacer un menú de texto con cuatro opciones que tenga el siguiente aspecto:

Seleccione una opción:
 1) Opción 1
 2) Opción 2
 3) Opción 3
 4) Salir
Opción:  

Si te fijas, he llamado de manera genérica a las tres primeras opciones, pero podrían ser algo como, si pensamos en un menú para trabajar con ficheros, Nuevo, Abrir y Guardar.

También añadimos una opción de Salir que suele ser habitual.

15 conceptos fundamentales que necesitas conocer para aprender y dominar Python

Te voy a hacer dos regalos (no uno, sino dos) que hablan de estos 15 conceptos fundamentales de Python: mi Tutorial Básico Interactivo de Python y una cheat sheet de Python en español: La Hoja de Referencia de Python.

Estos regalos son exclusivos para los suscriptores de Código Pitón.

👍 Quiero mis dos regalos

Además, junto a cada opción hay un número. Ese número permite al usuario seleccionar la opción asociada sin necesidad de escribir el nombre de dicha opción. Podrían ser letras también, como A), B) y C) o incluso se podrían usar dos o más caracteres para cada opción: Op1), Op2) y Op3). A este número o letra o conjuntos de letras y números lo llamaremos selector.

Pues bien, vamos a guardar en un diccionario, nuestro diccionario de opciones, tuplas de dos elementos: el nombre de la opción y la acción asociada a dicha opción. Y vamos a utilizar el selector correspondiente como clave para cada una de las tuplas de opción y acción:

opciones = {
    '1': ('Opción 1', accion1),
    '2': ('Opción 2', accion2),
    '3': ('Opción 3', accion3),
    '4': ('Salir', salir)
}

Si te fijas, en cada tupla tenemos dos elementos. El primero de ellos es el nombre de la opción que saldrá en el menú. El segundo es el nombre de una función. Dicha función se ejecutará al seleccionar esa opción.

Podemos almacenar el nombre de una función en una variable, o en una tupla en este caso, porque en Python las funciones son elementos de primer orden. Gracias a esto podemos invocar a la función sin necesidad de conocer su nombre.

Para poder hacer esto tienen que estar definidas las funciones accion1, accion2, accion3 y salir. Vamos a definirlas de la siguiente manera:

def accion1():
    print('Has elegido la opción 1')


def accion2():
    print('Has elegido la opción 2')


def accion3():
    print('Has elegido la opción 3')


def salir():
    print('Saliendo')

Ya ves que en este caso nuestras funciones solo imprimen un mensaje por pantalla. Pero evidentemente tú pondrás en ellas el código que te interese ejecutar.

Creando la lógica del menú

Hasta aquí nos hemos ocupado de nuestras opciones y acciones. Toca ahora encargarse de la lógica del menú.

Para ello haremos un bucle en que realizaremos tres cosas claramente diferenciadas:

  1. Mostrar el menú al usuario
  2. Pedir una opción al usuario y leer esa opción por teclado.
  3. Ejecutar la opción correspondiente.

Queremos hacerlo en un bucle porque el usuario puede querer ejecutar varias acciones hasta que decida salir. Es por esto que hemos puesta esa cuarta opción en el menú.

Para ser organizados, vamos a crear una serie de funciones que faciliten tanto la explicación como la lectura y que, además, nos permita la reutilización de código en caso de que sea necesario.

Primeramente vamos a crear una función menu_principal que contenga las opciones del menú que ya creamos más arriba así como una llamada a otra función generar_menu que recibe como parámetro el diccionario de opciones y el selector de la opción de salir. Gracias a estos parámetros, ya estamos independizando la función generar_menu de las opciones, condición que establecimos al principio de este apartado.

La función nos queda de la siguiente manera:

def menu_principal():
    opciones = {
        '1': ('Opción 1', accion1),
        '2': ('Opción 2', accion2),
        '3': ('Opción 3', accion3),
        '4': ('Salir', salir)
    }

    generar_menu(opciones, '4')

Veamos ahora cómo implementar la función generar_menu, en la que realizaremos el bucle explicado previamente:

def generar_menu(opciones, opcion_salida):
    opcion = None
    while opcion != opcion_salida:
        mostrar_menu(opciones)
        opcion = leer_opcion(opciones)
        ejecutar_opcion(opcion, opciones)
        print() # se imprime una línea en blanco para clarificar la salida por pantalla

Si te fijas en el bucle podrás ver tres líneas principales (de la 4 a la 6) en la que se realizan exactamente las tres tareas del bucle de menú: mostrar el menú, leer la opción del usuario y ejecutar la acción asociada a esa opción.

He encapsulado estas tres tareas en funciones como dije antes, así que vamos a verlas una a una.

Para mostrar el menú creamos una función mostrar_menu que necesita recibir el diccionario de opciones, pues es donde están almacenados los selectores y el nombre de las opciones:

def mostrar_menu(opciones):
    print('Seleccione una opción:')
    for clave in sorted(opciones):
        print(f' {clave}) {opciones[clave][0]}')

Lo único que hay que hacer en esta función es recorrer el diccionario en un bucle mostrando una línea por iteración. En cada línea se imprime por pantalla el selector y el nombre de la opción. Adicionalmente, usando la función integrada sorted ordenamos el diccionario para que salgan las opciones en el orden natural establecido por el selector.

De la segunda tarea del bucle, solicitar una opción al usuario y leerla de teclado, se encargará la función leer_opcion. Esta función recibe un único parámetro que es el diccionario de opciones. Es necesario para poder determinar si lo que introduce el usuario por teclado es un selector válido:

Recibe contenido exclusivo y obtén gratis la Hoja de Referencia de Python.

Antes de suscribirte consulta aquí la 
Información Básica sobre Protección de Datos. Responsable de datos: Juan Monroy Camafreita. Finalidad de recogida y tratamiento de datos personales: enviarte boletín informativo de Python y comunicaciones comerciales. Legitimación: tu consentimiento. Destinatarios: no se ceden a terceros. Los datos se almacenan en los servidores de marketing (MailRelay). Derechos: podrás ejercer tus derechos de acceso, rectificación, limitación y supresión de datos en info @ codigopiton.com así como presentar una reclamación ante una autoridad de control. Más información: política de privacidad, encontrarás información adicional sobre la recopilación y el uso de tu información personal.
def leer_opcion(opciones):
    while (a := input('Opción: ')) not in opciones:
        print('Opción incorrecta, vuelva a intentarlo.')
    return a

En este código puedes ver que realizo un bucle para asegurarme de que el valor introducido por el usuario es válido, es decir, es uno de los posibles selectores del menú. Te explico esto en más detalle en este artículo: cómo pedir un valor al usuario hasta que sea válido.

Fíjate en que estoy usando el operador de la morsa :=. Este operador fue introducido en Python 3.8 y nos permite hacer una asignación a una variable y devolver el valor asignado.

La función leer_opcion devolverá el selector elegido por el usuario.

Finalmente, la función ejecutar_opcion recibirá la opción seleccionada y el diccionario de opción y ejecutará la acción correspondiente. Muy sencillo:

def ejecutar_opcion(opcion, opciones):
    opciones[opcion][1]()

Al terminar de ejecutarse la acción, se imprime una línea en blanco y se vuelve a ejecutar el cuerpo del bucle, excepto si el usuario ha elegido la opción de salir. Esto se hace mediante la condición del bucle opcion != opcion_salida.

Esta es una de las maneras de simular un switch case en Python como ya vimos en otro artículo de Código Pitón.

Y ya tenemos nuestro código completo:

def mostrar_menu(opciones):
    print('Seleccione una opción:')
    for clave in sorted(opciones):
        print(f' {clave}) {opciones[clave][0]}')


def leer_opcion(opciones):
    while (a := input('Opción: ')) not in opciones:
        print('Opción incorrecta, vuelva a intentarlo.')
    return a


def ejecutar_opcion(opcion, opciones):
    opciones[opcion][1]()


def generar_menu(opciones, opcion_salida):
    opcion = None
    while opcion != opcion_salida:
        mostrar_menu(opciones)
        opcion = leer_opcion(opciones)
        ejecutar_opcion(opcion, opciones)
        print()


def menu_principal():
    opciones = {
        '1': ('Opción 1', accion1),
        '2': ('Opción 2', accion2),
        '3': ('Opción 3', accion3),
        '4': ('Salir', salir)
    }

    generar_menu(opciones, '4')


def accion1():
    print('Has elegido la opción 1')


def accion2():
    print('Has elegido la opción 2')


def accion3():
    print('Has elegido la opción 3')


def salir():
    print('Saliendo')


if __name__ == '__main__':
    menu_principal()

Basta con invocar a la función menu_principal en nuestro programa principal, que se encargará de todo. Aquí vemos una posible ejecución del programa en el que el usuario introduce erróneamente la opción 5 y después ejecuta la 1, la 3 y finalmente sale seleccionando la opción 4:

Seleccione una opción:
 1) Opción 1
 2) Opción 2
 3) Opción 3
 4) Salir
Opción: 5
Opción incorrecta, vuelva a intentarlo.
Opción: 1
Has elegido la opción 1

Seleccione una opción:
 1) Opción 1
 2) Opción 2
 3) Opción 3
 4) Salir
Opción: 3
Has elegido la opción 3

Seleccione una opción:
 1) Opción 1
 2) Opción 2
 3) Opción 3
 4) Salir
Opción: 4
Saliendo

Cómo hacer un submenú de texto

Vamos a modificar levemente nuestro código para poder incluir submenús si los necesitamos. Puede suceder que algunas de la opciones de un menú lleven a otro menú con nuevas opciones. A esto es a lo que llamo submenú.

Realmente, si has leído hasta aquí, ya tienes las herramientas necesarias para poder hacer un menú con submenús.

Basta con realizar una llamada a la función generar_menu en la acción del menú original que deba mostrar otro menú, pasando como parámetro el diccionario de opciones del submenú.

Te lo ilustro a continuación, pero antes vamos a hacer otro pequeño cambio ya que se van a mostrar diferentes menús. Para ayudar al usuario a entender en qué menú está, vamos a ponerle un nombre a cada menú y a mostrarlo por pantalla. Algo similar a esto:

# Menú principal. Seleccione una opción:
 1) Opción 1
 2) Opción 2 >
 3) Opción 3
 4) Salir
Opción: 

Para lograr esto basta con añadir un nuevo parámetro a la función generar_menu en el que se indique, precisamente ese nombre. Además, ese nombre será pasado como parámetro, a su vez, a la función mostrar_menu que imprimirá por pantalla el menú con su nombre.

En esta ocasión vamos a crear un menú principal con tres opciones más la opción de salir. La opción 2 servirá para llevar a otro menú que tenga dos nuevas opciones (opción a y opción b) más la opción de salir.

La opción de salir del submenú hará que volvamos al menú principal, pues todavía seguimos en el bucle principal de dicho menú. Gracias a esto la navegación por los distintos menús será muy fluida para el usuario. Veamos el código completo:

def mostrar_menu(nombre, opciones):  # incorporamos el parámetro para mostrar el nombre del menú
    print(f'# {nombre}. Seleccione una opción:')
    for clave in sorted(opciones):
        print(f' {clave}) {opciones[clave][0]}')


def leer_opcion(opciones):
    while (a := input('Opción: ')) not in opciones:
        print('Opción incorrecta, vuelva a intentarlo.')
    return a


def ejecutar_opcion(opcion, opciones):
    opciones[opcion][1]()


def generar_menu(nombre, opciones, opcion_salida):  # incorporamos el parámetro para mostrar el nombre del menú
    opcion = None
    while opcion != opcion_salida:
        mostrar_menu(nombre, opciones)
        opcion = leer_opcion(opciones)
        ejecutar_opcion(opcion, opciones)
        print()


def menu_principal():
    opciones = {
        '1': ('Opción 1', funcion1),
        '2': ('Opción 2 >', submenu),  # la acción es una llamada a submenu que genera un nuevo menú
        '3': ('Opción 3', funcion3),
        '4': ('Salir', salir)
    }

    generar_menu('Menú principal', opciones, '4')  # indicamos el nombre del menú


def submenu():
    opciones = {
        'a': ('Opción a', funcionA),
        'b': ('Opción b', funcionB),
        'c': ('Volver al menú principal', salir)
    }

    generar_menu('Submenú', opciones, 'c')  # indicamos el nombre del submenú


# A partir de aquí creamos las funciones que ejecutan las acciones de los menús
def funcion1():
    print('Has elegido la opción 1')


def funcion2():
    print('Has elegido la opción 2')


def funcion3():
    print('Has elegido la opción 3')


def funcionA():
    print('Has elegido la opción A')


def funcionB():
    print('Has elegido la opción B')


def salir():
    print('Saliendo')


if __name__ == '__main__':
    menu_principal() # iniciamos el programa mostrando el menú principal

Si ejecutamos el código de arriba y el usuario accede al submenú, selecciona la opción b, después regresa al menú principal y selecciona la opción de salir tendremos la siguiente ejecución:

# Menú principal. Seleccione una opción:
 1) Opción 1
 2) Opción 2 >
 3) Opción 3
 4) Salir
Opción: 2
# Submenú. Seleccione una opción:
 a) Opción a
 b) Opción b
 c) Volver al menú principal
Opción: b
Has elegido la opción B

# Submenú. Seleccione una opción:
 a) Opción a
 b) Opción b
 c) Volver al menú principal
Opción: c
Saliendo


# Menú principal. Seleccione una opción:
 1) Opción 1
 2) Opción 2 >
 3) Opción 3
 4) Salir
Opción: 4
Saliendo

Espero que te haya servido de utilidad. Pasemos a ver a continuación cómo realizar un menú en el caso de que estemos utilizando las librerías tkinter o PyQt5.

Cómo hacer un menú con Python y tkinter

Si tienes que realizar una aplicación Tcl/Tk puedes usar la librería de Python tkinter.

Para hacer un menú en Python y tkinter hay que usar la clase Menu para crear una barra de menús y tantos menús como desees agregar. La función add_command te permitirá añadir una nueva opción a un menú y add_cascade te permitirá añadir un menú a la barra de menús o un submenú a otro menú.

El proceso que vamos a seguir tiene unos cuantos pasos pero es muy sencillo. Es de la siguiente manera:

  1. Primero necesitamos crear una ventana. Lo haremos con la clase Tk.
  2. Después crearemos una barra de menús, la típica barra que se ubica en la parte superior de las aplicaciones. Usaremos la clase Menu para ello y configuraremos la ventana para indicarle que vamos a usar esa barra de menús.
  3. Crearemos un menú, nuevamente, con la clase Menu, al que añadiremos opciones mediante la función add_command. Añadimos el menú a la barra de menús mediante la función add_cascade.
  4. Para crear un submenú usamos de nuevo la clase Menu, le añadimos opciones y lo añadimos al menú principal con la función add_cascade.
  5. Añadimos los menús que hagan falta a la barra de menús o a otros menús.
  6. Finalmente mostramos y ejecutamos la ventana creada mediante la función mainloop.

Te lo explico paso a paso para que no haya pérdida y al final te pongo todo el código del ejemplo.

Asegúrate de tener instalado el módulo tkinter. Puedes hacerlo con pip install tkinter.

Lo primero es importar el módulo tkinter y crear la ventana principal, a la que le daremos un tamaño de 800 x 600 píxeles:

import tkinter as tk

ventana = tk.Tk()
ventana.title('Ventana principal')
ventana.geometry('800x600')

Ahora vamos a crear la barra de menús que se ubicará en la parte superior de la ventana. Para ello creamos un objeto de la clase Menu. Después configuramos la ventana creada proporcionándole la barra de menús a través del parámetro menu:

barra_menus = tk.Menu(ventana)
ventana.config(menu=barra_menus)

Lo siguiente es crear el menú. Hacemos uso, nuevamente, de la clase Menu. Su contenedor será la barra de menús. Además, indicamos mediante el parámetro tearoff que no se muestre el botón que permite desanclar el menú de la barra, aunque esto es opcional, claro:

menu = tk.Menu(barra_menus, tearoff=False)

Añadiremos dos opciones al menú: Opción 1 y Opción 2. Al igual que hacíamos al realizar un menú en modo texto, vamos a indicar el nombre de la opción mediante el parámetro labely la acción a ejecutar mediante el parámetro command. Estas acciones deben ser nombres de funciones (en nuestro caso, accion1 y accion2). Estas funciones las definiremos más tarde:

menu.add_command(label='Opción 1', command=accion1)
menu.add_command(label='Opción 2', command=accion2)

Ahora vamos a añadir un submenú. Para esto hay que crear otro menú, indicar que pertenece al menú principal y añadirle otro par de opciones y sus acciones correspondientes:

submenu = tk.Menu(menu, tearoff=False)
submenu.add_command(label='Opción A', command=acciona)
submenu.add_command(label='Opción B', command=accionb)

Tenemos que añadir ahora el submenú al menú principal utilizando la función add_cascade que permite agregar un menú en cascada:

menu.add_cascade(label='Submenú', menu=submenu)

Ya falta menos. Vamos a añadir una línea separadora con la función add_separator y finalmente una opción para salir del programa, indicando que su acción es ventana.destroy, que nos sirve precisamente para destruir la ventana:

menu.add_separator()
menu.add_command(label='Salir', command=ventana.destroy)

Finalmente añadimos el menú creado a la barra de menús con la función add_cascade:

barra_menus.add_cascade(label="Menú", menu=menu)

Para comprobar que las acciones del menú efectivamente funcionan vamos a crear una etiqueta de texto con la clase Label y la ubicaremos en la ventana, en la posición (200, 200) con la función place.

texto = tk.Label(ventana, text='¡Hola, desde Código Pitón!')
texto.place(x=200, y=200)

Y nos queda definir las acciones como dije anteriormente. Tenemos cuatro acciones en total, dos en el menú principal y dos en el submenú. Creamos las funciones y les ponemos un código muy sencillo. Lo que harán es cambiar el mensaje de texto de la etiqueta creada anteriormente:

def accion1():
    texto.configure(text='Has elegido la opción 1 del menú principal')


def accion2():
    texto.configure(text='Has elegido la opción 2 del menú principal')


def acciona():
    texto.configure(text='Has elegido la opción a del submenú')


def accionb():
    texto.configure(text='Has elegido la opción b del submenú')

¡Y ya lo tenemos! Son unos cuantos pasos, sí, pero el procedimiento es muy directo y sencillo como puedes ver.

Ahora basta con ejecutar ventana.mainloop() y tendremos nuestra aplicación funcionando con su fantástico menú:

Ejemplo de menú hecho con Python y tkinter
Menú realizado con Python y tkinter

Y aquí tienes el código completo de un menú de usuario con submenú hecho con tkinter y Python:

import tkinter as tk

# definimos las acciones asociadas a las opciones de los menús
def accion1():
    texto.configure(text='Has elegido la opción 1 del menú principal')


def accion2():
    texto.configure(text='Has elegido la opción 2 del menú principal')


def acciona():
    texto.configure(text='Has elegido la opción a del submenú')


def accionb():
    texto.configure(text='Has elegido la opción b del submenú')


# creamos la ventana principal
ventana = tk.Tk()
ventana.title('Ventana principal')
ventana.geometry('800x600')

# creamos una barra de menús y la añadimos a la ventana principal
# cada ventana solo puede tener una barra de menús
barra_menus = tk.Menu(ventana)
ventana.config(menu=barra_menus)

# creamos un menú cuyo contenedor será la barra de menús
menu = tk.Menu(barra_menus, tearoff=False)

# añadimos opciones al menú indicando su nombre y acción asociado
menu.add_command(label='Opción 1', command=accion1)
menu.add_command(label='Opción 2', command=accion2)

# creamos un submenú
submenu = tk.Menu(menu, tearoff=False)
submenu.add_command(label='Opción A', command=acciona)
submenu.add_command(label='Opción B', command=accionb)

# añadimos un submenú al menú principal
menu.add_cascade(label='Submenú', menu=submenu)

# añadimos una línea separadora y la opción de salir
menu.add_separator()
menu.add_command(label='Salir', command=ventana.destroy)

# finalmente añadimos el menú a la barra de menús
barra_menus.add_cascade(label="Menú", menu=menu)

# añadimos una etiqueta para ver el efecto de los botones del menú
texto = tk.Label(ventana, text='¡Hola, desde Código Pitón!')
texto.place(x=200, y=200)


if __name__ == '__main__':
    ventana.mainloop()  # ejecutamos la ventana principal

Cómo hacer un menú con Python y PyQT

Si tienes que realizar una aplicación Qt puedes utilizar la librería de Python PyQt5.

Para hacer un menú en Python y PyQt5 hay que extender la clase QMainWindow y añadir una barra de menús con la función menuBar a la que se añade un menú con la función addMenu. Con addAction se incorporan opciones al menú que son objetos de la clase QAction. Se puede incluir un submenú con addMenu.

El proceso para crear el menú en PyQt es de la siguiente manera:

  1. Primero crearemos la clase de nuestra ventana extendiendo la clase QMainWindow.
  2. En la función constructora __init__ crearemos una barra de menús, la barra superior, llamando a la función menuBar de la propia clase y que es heredada de QMainWindow.
  3. Crearemos un menú invocando a la función addMenu de la barra de menús y le daremos un nombre.
  4. Se instancian tantos objetos QAction como opciones necesitemos en el menú. Conectaremos a las opciones las acciones correspondientes y después las añadiremos al menú con la función addAction.
  5. Para crear un submenú creamos un objeto de la clase QMenu y le añadimos opciones de la misma forma que en el paso anterior.
  6. Añadimos los menús que hagan falta a la barra de menús o a otros menús.
  7. Finalmente creamos un objeto de nuestra clase ventana y la ejecutamos con exec.

Te lo explico paso a paso, que son unas cuantas cosas, para que que sigas bien el procedimiento y al final te pongo todo el código del ejemplo.

Asegúrate de tener instalado el módulo PyQt5. Puedes hacer con el comando pip install PyQt5.

Lo primero es importar la librería PyQt5. Como vamos a necesitar varios componentes los importaremos todos: son QMainWindow, QApplication, QLabel, QAction, qApp, QMenu. Pero no te preocupes, que iremos viéndolos poco a poco. También necesitaremos importar la librería sys.

Crearemos una clase, que vamos a llamar VentanaPrincipal que debe extender a QMainWindow que es una extensión de QWidget y que nos proporciona facilidades para crear ventanas. Por comodidad, ubicaremos casi todo el código de creación del menú dentro de la función constructora __init__:

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QAction, qApp, QMenu


class VentanaPrincipal(QMainWindow):
    def __init__(self):
        super().__init__()

Ahora continuamos añadiendo código a __init__. Empezamos configurando la ventana, a la que le damos un nombre y le ponemos un tamaño fijo en este caso:

        self.setWindowTitle('Ventana principal')
        self.setFixedWidth(800)
        self.setFixedHeight(700)

Al igual que hicimos en el caso anterior con tkinter, vamos a crear una etiqueta de texto cuyo texto vamos a modificar como resultado de elegir alguna de las opciones del menú, para poder comprobar su funcionamiento. Para eso creamos el objeto QLabel y lo ubicamos en nuestra ventana como elemento central:

        self.texto = QLabel('¡Hola, desde Código Pitón!')
        self.setCentralWidget(self.texto)

Ahora crearemos una barra de menús utilizando la función menuBar heredada de QMainWindow. Además, añadiremos un menú llamado Principal a nuestra barra. Fíjate en que en el nombre del menú antepongo el símbolo & a la P. Esto nos sirve para indicar que podremos abrir el menú principal pulsando la letra P. También aparecerá subrayada esa letra en la ventana.

        barra_menus = self.menuBar()
        menu = barra_menus.addMenu('&Principal')

Ahora toca añadir opciones al menú. Para esto tendremos que instanciar objetos de la clase QAction, conectar una acción a esos objetos. Finalmente añadiremos cada opción al menú deseado. El constructor de QAction que estamos usando recibe dos parámetros: el nombre de la opción (fíjate en que también uso el truco de anteponer & al carácter deseado) y un objeto que será el padre de la opción, que por ejemplo pueden ser menu o self (si queremos que el padre sea la ventana).

Para conectar la acción con la opción tendremos que que utilizar la función connect del evento de disparo de la opción triggered. Las acciones conectadas deben ser nombres de funciones, en este caso son dos funciones privadas de la clase de ventana que definiremos más adelante. Para añadir la opción al menú usaremos la función addAction:

        opcion_1 = QAction('Opción &1', menu)
        opcion_1.triggered.connect(self.opcion_1)
        menu.addAction(opcion_1)

        opcion_2 = QAction('Opción &2', menu)
        opcion_2.triggered.connect(self.opcion_2)
        menu.addAction(opcion_2)

Ya tenemos un menú con dos opciones, ahora vamos a crear un submenú. Para ello instanciaremos un objeto QMenu proporcionando un nombre de menú e indicando el objeto padre. Después añadiremos el submenú al menú principal. También crearemos otras dos opciones para este submenú, de la misma manera que vimos anteriormente:

        submenu = QMenu('&Submenú', menu)
        menu.addMenu(submenu)

        opcion_a = QAction('Opción &a', menu)
        opcion_a.triggered.connect(self.opcion_a)
        submenu.addAction(opcion_a)

        opcion_b = QAction('Opción &b', menu)
        opcion_b.triggered.connect(self.opcion_b)
        submenu.addAction(opcion_b)

Para terminar añadiremos un separador al menú principal y después una opción para salir de la ventana principal (y del programa). Para el separador usaremos la función addSeparator y para la opción de salir conectaremos una función especialmente diseñada para esa tarea que es qApp.quit:

        menu.addSeparator()

        accion_salir = QAction('&Salir', menu)
        accion_salir.triggered.connect(qApp.quit)
        menu.addAction(accion_salir)

Para terminar de completar el código definiremos las funciones de acción asociadas a las opciones del menú, cosa que hicimos previamente con la función connect. Lo único que harán estas acciones es cambiar el texto de la etiqueta creada anteriormente:

    def opcion_1(self):
        self.texto.setText('Has elegido la opción 1 del menú principal')

    def opcion_2(self):
        self.texto.setText('Has elegido la opción 2 del menú principal')

    def opcion_a(self):
        self.texto.setText('Has elegido la opción a del submenú')

    def opcion_b(self):
        self.texto.setText('Has elegido la opción b del submenú')

Y ya solo nos queda instanciar nuestra aplicacion (clase QApplication), nuestra ventana principal, que debemos mostrar con su función show y, finalmente, ejecutar la aplicación. Para esto llamaremos a la función exec de la aplicación. Una vez que la venta se cierre se pasará el resultado a la función sys.exit para que finalice el script:

if __name__ == '__main__':

    aplicacion = QApplication([])

    ventana = VentanaPrincipal()
    ventana.show()

    sys.exit(aplicacion.exec())

Aquí te muestro la ventana que hemos creado con PyQt5 y con el menú desplegado:

Ejemplo de menú hecho con Python y PyQt5
Menú realizado con Python y PyQt5

Para terminar, aquí tienes el código completo para que puedas reutilizarlo y modificarlo a tu gusto y según tus necesidades:

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QAction, qApp, QMenu


# creamos la clase de la venta princiap
class VentanaPrincipal(QMainWindow):
    def __init__(self):
        super().__init__()

        # configuramos la ventana con un título y un tamaño
        self.setWindowTitle('Ventana principal')
        self.setFixedWidth(800)
        self.setFixedHeight(700)

        # creamos una etiqueta de texto y la ubicamos en la ventana
        self.texto = QLabel('¡Hola, desde Código Pitón!')
        self.setCentralWidget(self.texto)

        # creamos la barra de menús y añadimos un menú
        barra_menus = self.menuBar()
        menu = barra_menus.addMenu('&Principal')

        # creamos dos opciones para el menú principal
        opcion_1 = QAction('Opción &1', menu)
        opcion_1.triggered.connect(self.opcion_1)
        menu.addAction(opcion_1)

        opcion_2 = QAction('Opción &2', menu)
        opcion_2.triggered.connect(self.opcion_2)
        menu.addAction(opcion_2)

        # creamos un submenú que añadimos al menú principal
        submenu = QMenu('&Submenú', menu)
        menu.addMenu(submenu)

        # añadimos opciones al submenú
        opcion_a = QAction('Opción &a', menu)
        opcion_a.triggered.connect(self.opcion_a)
        submenu.addAction(opcion_a)

        opcion_b = QAction('Opción &b', menu)
        opcion_b.triggered.connect(self.opcion_b)
        submenu.addAction(opcion_b)

        # creamos un separador y la opción de salir en el menú principal
        menu.addSeparator()

        accion_salir = QAction('&Salir', menu)
        accion_salir.triggered.connect(qApp.quit)
        menu.addAction(accion_salir)
        
        
    # definimos las acciones las opciones de los menús
    def opcion_1(self):
        self.texto.setText('Has elegido la opción 1 del menú principal')

    def opcion_2(self):
        self.texto.setText('Has elegido la opción 2 del menú principal')

    def opcion_a(self):
        self.texto.setText('Has elegido la opción a del submenú')

    def opcion_b(self):
        self.texto.setText('Has elegido la opción b del submenú')


if __name__ == '__main__':

    # creamos una aplicación PyQT
    aplicacion = QApplication([])

    # creamos la ventana principal
    ventana = VentanaPrincipal()
    ventana.show()

    # ejecutamos la aplicación y terminamos el programa al cerrarse la ventana
    sys.exit(aplicacion.exec())

Conclusión

Hasta aquí el artículo. Te he dado tres de las opciones más comunes para realizar menus de usuario con diferentes opciones y submenús en Python.

He intentado mantener el código tan sencillo como sea posible, es decir, he creado una base sobre la que puedes trabajar y añadir diversas funcionalidades y características.

Si te ha gustado este artículo no dudes en suscribirte a la newsletter para estar enterado de actualizaciones. Además, recibirás trucos y consejos de vez en cuando y te regalaré La Hoja de Referencia de Python de Código Pitón. ¡Y puedes darte de baja cuando quieras!

 🎁 Tutorial Básico Interactivo y La Hoja de Referencia de Python – ¡Gratis!

La Hoja de Referencia de Python - Código Pitón
¿Quieres mejorar tu Python? Recibe totalmente gratis el Tutorial Básico Interactivo de Python, la Hoja de Referencia de Python y contenido exclusivo como trucos y consejos.



Antes de suscribirte consulta aquí la Información Básica sobre Protección de Datos. Responsable de los datos: Juan Monroy Camafreita. Finalidad de la recogida y tratamiento de los datos personales: enviarte boletín informativo de Python y comunicaciones comerciales. Legitimación: tu consentimiento. Destinatarios: no se ceden a terceros. Los datos se almacenan en los servidores de marketing (MailRelay). Derechos: podrás ejercer tus derechos de acceso, rectificación, limitación y supresión de datos en info @ codigopiton.com así como presentar una reclamación ante una autoridad de control. Más información en nuestra política de privacidad, encontrarás información adicional sobre la recopilación y el uso de tu información personal, incluida información sobre acceso, conservación, rectificación, eliminación, seguridad y otros temas.