¿Te gustaría aprender a crear una interfaz gráfica de usuario (GUI) con Python? ¿Quieres darle un aspecto profesional y funcional a tus aplicaciones de escritorio? Entonces este tutorial es para ti. En este artículo te enseñaré cómo crear un menú superior con tkinter, una de las bibliotecas más populares y sencillas para crear GUIs con Python. Un menú superior es una barra que se ubica en la parte superior de la ventana y que contiene diferentes opciones y funciones que el usuario puede seleccionar. Con tkinter puedes crear menús superiores de forma fácil y rápida, siguiendo unos pocos pasos que te explicaré a continuación. Además, podrás personalizar el aspecto y el comportamiento de tus menús según tus preferencias y necesidades. ¿Estáis listos para empezar? ¡Pues vamos allá!
Importar Tkinter y crear el menú
Primero, debes importar Tkinter.
# Importación de Tkinter import tkinter as tk
Después, hay que crear un objeto de tipo menú. Este lo instanciamos de la clase "Menu" de Tkinter.
# Se crea el menú de la ventana menu = tk.Menu()
Crear opciones principales para el menú de Tkinter
Lo siguiente que haremos, será crear objetos para cada opción principal, las típicas de Archivo, Edición, etc.
Con el primero argumento, especificamos donde aparecen (menu) y con el segundo (tearoff con 0), hacemos que el menú sea fijo, comportamiento por defecto (luego explico la opción alternativa).
Con el nombre del objeto del menú, utilizando su método add_cascade(), vamos a añadir cada uno de los objetos al menú asociándolos a una etiqueta.
# Se crean las opciones principales menu_archivo = tk.Menu(menu, tearoff=0) menu_editar = tk.Menu(menu, tearoff=0) menu_ayuda = tk.Menu(menu, tearoff=0) # Agregar las opciones principales al menú menu.add_cascade(label="Archivo", menu=menu_archivo) menu.add_cascade(label="Editar", menu=menu_editar) menu.add_cascade(label="Ayuda", menu=menu_ayuda)
Crear subopciones para el menú de Tkinter
Cuando ya tengas todas las opciones principales añadidas a tu menú, le puedes añadir subopciones para que se despliegue el menú con las que necesites.
Esto lo hacemos asociando a cada objeto de opción principal una nueva etiqueta con el método add_command:
# Se crean las subopciones para "Archivo" menu_archivo.add_command(label="Abrir") menu_archivo.add_command(label="Guardar") menu_archivo.add_separator() menu_archivo.add_command(label="Salir", command=root.quit) # Se crean las subopciones para "Editar" menu_editar.add_command(label="Cortar") menu_editar.add_command(label="Copiar") menu_editar.add_command(label="Pegar")
Si quieres que una opción principal no tenga subopciones, la dejas sin "add_command", como el caso de "menu_ayuda", que no le añado ninguna opción.
Para hacer que los botones realicen acciones, utiliza el sistema de siempre con los botones de Tkinter, el "command" con la llamada a una función o método.
En el ejemplo de "Salir", he llamado al método quit() de Tkinter para que finalice el programa si se pulsa, solo para que veas un ejemplo de uso.
Ya solo queda lo último, hemos empezado la casa por el tejado. Hay que colocar el menú en la ventana, en mi caso, se llama root:
# Se muestra la barra de menú en la ventana principal root.config(menu=menu)
Que no te confunda "menu=menu", el primero, es el nombre del atributo de la ventana root destinado a colocar un menú. El segundo, es el nombre del objeto que hemos creado. Si crees que esto crea confusión, llámalo por ejemplo "menu_superior".
Esto quedaría así:
root.config(menu=menu_superior)
Vamos a probar esto:

El resultado es tal y como esperamos en cualquier programa.
Añadir más opciones dentro de las subopciones
Lo siguiente que puede que necesites, es añadir más opciones anidadas dentro de las subopciones. Esto es tan fácil como utilizar de nuevo "add_command" con alguna de las subopciones. En este caso, el "add_cascade" tiene que ser aplicado con la opción principal (menu_archivo, por ejemplo).
# Se crean las subopciones para "Archivo > Abrir" menu_preferencias = tk.Menu(menu_archivo, tearoff=0) menu_preferencias.add_command(label="Opción 1") menu_preferencias.add_command(label="Opción 2") menu_preferencias.add_command(label="Opción 3") # Se añaden las subopciones de "Abrir" al menú "Archivo" menu_archivo.add_cascade(label="Abrir", menu=menu_preferencias)
Crear menús desacopables con Tkinter
Queda solo explicar el tema del atributo "tearoff".
El atributo "tearoff" con un valor de 0, crea un menú fijo como el que acabas de ver, sin embargo, puedes hacer que un menú se pueda desacoplar con el valor 1.
He puesto en 1 estos dos elementos, el resto a 0.
menu_editar = tk.Menu(menu, tearoff=1) ... menu_preferencias = tk.Menu(menu_archivo, tearoff=1)
El resultado es que se pueden separar esas partes del menú en pequeñas ventanas adicionales.

Te dejo el código completo aquí por si has tenido problemas para seguir el hilo en alguna parte:
# Importación de Tkinter import tkinter as tk # Se crea la ventana del programa root = tk.Tk() # Se crea el menú de la ventana menu = tk.Menu() # Se crean las opciones principales menu_archivo = tk.Menu(menu, tearoff=0) menu_editar = tk.Menu(menu, tearoff=0) menu_ayuda = tk.Menu(menu, tearoff=0) # Agregar las opciones principales al menú menu.add_cascade(label="Archivo", menu=menu_archivo) menu.add_cascade(label="Editar", menu=menu_editar) menu.add_cascade(label="Ayuda", menu=menu_ayuda) # Se crean las subopciones para "Archivo" menu_archivo.add_command(label="Abrir") menu_archivo.add_command(label="Guardar") menu_archivo.add_separator() menu_archivo.add_command(label="Salir", command=root.quit) # Se crean las subopciones para "Editar" menu_editar.add_command(label="Cortar") menu_editar.add_command(label="Copiar") menu_editar.add_command(label="Pegar") # Se crean las subopciones para "Archivo > Preferencias" menu_preferencias = tk.Menu(menu_archivo, tearoff=0) menu_preferencias.add_command(label="Opción 1") menu_preferencias.add_command(label="Opción 2") menu_preferencias.add_command(label="Opción 3") # Se crea la cascada de "Preferencias" al menú "Archivo" menu_archivo.add_cascade(label="Preferencias", menu=menu_preferencias) # Se muestra la barra de menú en la ventana principal root.config(menu=menu) # Bucle de ejecución del programa root.mainloop()
Adaptar los menús de Tkinter a CustomTkinter
Para quienes utilizáis CustomTkinter, tengo una mala noticia, no tiene menús superiores, hay que utilizar los propios de Tkinter.
Pues bien, hago esta última sección para que veáis de qué forma podéis crear un menú superior de Tkinter en una ventana de tipo CTk e CustomTkinter.
La forma de hacer esto, es más engorrosa, ya que tenemos que crear los botones del menú por nuestra cuenta.
Primero, en la línea 10, creo un frame para el menú. Lo posiciono en la parte superior.
Después, en la línea 15 hago uso de una cosa nueva de Tkinter, los Menubutton, que son botones sueltos de menú.
Con estos Menubutton, podemos ir creando la barra de menú superior.
Lo bueno de usarlos, es que permiten personalizarse de manera relativamente fácil, cosa que no podemos hacer con el menú nativo de Windows (en donde estoy explicando) que utiliza Tkinter.
En la línea 21 y 22, creo menús desplegables para cada Menubutton.
Después, ya podemos ir añadiendo opciones con "add_command()" a los menús.
# Se importa Tkinter import tkinter as tk # Se crea la ventana con un tamaño y color de fondo root = tk.Tk() root.geometry("400x200") root.config(background="gray17") # Se crea un frame para contener el menu menu_frame = tk.Frame(root, background='black') # Posiciona el Frame en la parte superior de la ventana menu_frame.pack(side='top', fill='x') # Crea un Menubutton dentro del Frame archivo = tk.Menubutton(menu_frame, text='Archivo', background='black', foreground='white', activeforeground='black', activebackground='gray52') # Crea un Menubutton dentro del Frame edicion = tk.Menubutton(menu_frame, text='Edición', background='black', foreground='white', activeforeground='black', activebackground='gray52') # Crea un menú desplegable para el Menubutton menu_archivo = tk.Menu(archivo, tearoff=0) menu_edicion = tk.Menu(edicion, tearoff=0) # Agrega una opción al menú desplegable menu_archivo.add_command(label='Imprimir', command=lambda: print('Hello PC Master!'), background='black', foreground='white', activeforeground='black', activebackground='gray52') # Asigna el menú desplegable al Menubutton archivo.config(menu=menu_archivo) # Posiciona el Menubutton dentro del Frame archivo.pack(side='left') root.mainloop()
Para quienes seguís el proyecto que estoy realizando en este curso, os dejo una adaptación de un menú en la interfaz de este.
Si no estás siguiendo este curso, ignora este código.
El color es para el modo oscuro. Aquí ya hay que añadir trabajo extra al utilizar CustomTkinter, ya que deberíamos crear dos menús solo para los dos modos de color.
En el vídeo de arriba explico mucho más:
class VentanaOpciones: # Diccionario para los botones botones = {'Consulta SQL': objeto_funciones.ventana_consultas, 'Mostrar Bases de Datos': objeto_funciones.ventana_mostrar_bases_datos, 'Eliminar Bases de Datos': objeto_funciones.ventana_eliminar_bases_datos, 'Crear Bases de Datos': objeto_funciones.ventana_crear_bases_datos, 'Crear Respaldos': objeto_funciones.ventana_crear_respaldos, 'Crear Tablas': objeto_funciones.ventana_crear_tablas, 'Eliminar Tablas': objeto_funciones.ventana_eliminar_tablas, 'Mostrar Tablas': objeto_funciones.ventana_mostrar_tablas, 'Mostrar Columnas': objeto_funciones.ventana_mostrar_columnas, 'Insertar Registros': objeto_funciones.ventana_insertar_registros, 'Eliminar Registros': objeto_funciones.ventana_eliminar_registros, 'Vaciar Tablas': objeto_funciones.ventana_vaciar_tablas, 'Actualizar Registros': objeto_funciones.ventana_actualizar_tablas } def __init__(self): # Se crea la ventana de CustomTkinter self.root = ctk.CTk() # Se le da un título self.root.title("Opciones para trabajar con bases de datos.") # Marco para contener el menú superior menu_frame = ctk.CTkFrame(self.root) menu_frame.pack(side='top', fill='x') # Se crea el botón de Menú archivo = tk.Menubutton(menu_frame, text='Archivo', background='#2b2b2b', foreground='white', activeforeground='black', activebackground='gray52') # Se crea el botón de Menú edicion = tk.Menubutton(menu_frame, text='Edición', background='#2b2b2b', foreground='white', activeforeground='black', activebackground='gray52') # Se crea el menú menu_archivo = tk.Menu(archivo, tearoff=0) # Se crea el menú menu_edicion = tk.Menu(edicion, tearoff=0) # Añade una opción al menú desplegable menu_archivo.add_command(label='Imprimir Saludo', command=lambda: print('Hello PC Master!'), background='#2b2b2b', foreground='white', activeforeground='black', activebackground='gray52') # Crea un nuevo menú para la cascada cascada = tk.Menubutton(menu_edicion, text='Cascada', background='black', foreground='white', activeforeground='black', activebackground='gray52') # Se crea el menú menu_cascada = tk.Menu(cascada, tearoff=0) cascada.config(menu=menu_cascada) # Se crea una cascada dentro del menu de edición menu_edicion.add_cascade(label="Opciones", menu=menu_cascada, background='#2b2b2b', foreground='white', activeforeground='black', activebackground='gray52') # Agrega opciones a la cascada menu_cascada.add_command(label="Opción 1", command=lambda: print("Opción 1 seleccionada"), background='#2b2b2b', foreground='white', activeforeground='black', activebackground='gray52') menu_cascada.add_command(label="Opción 2", command=lambda: print("Opción 2 seleccionada"), background='#2b2b2b', foreground='white', activeforeground='black', activebackground='gray52') menu_cascada.add_command(label="Opción 3", command=lambda: print("Opción 3 seleccionada"), background='#2b2b2b', foreground='white', activeforeground='black', activebackground='gray52') # Asigna el menú desplegable al Menubutton archivo.config(menu=menu_archivo) # Posiciona el Menubutton dentro del Frame archivo.pack(side='left') # Asigna el menú desplegable al Menubutton edicion.config(menu=menu_edicion) # Posiciona el Menubutton dentro del Frame edicion.pack(side='left') # Asigna el menú desplegable al Menubutton cascada.config(menu=menu_cascada) # Crea un Frame para contener los botones de la ventana frame_botones = ctk.CTkFrame(self.root) # Posiciona el Frame debajo del menú frame_botones.pack(side='top', fill='x') # Contador para la posición de los botones contador = 0 # Valor de elementos por fila elementos_fila = 3 # Crea los botones y establece su texto for texto_boton in self.botones: boton = ctk.CTkButton( master=frame_botones, #Se le indica en que frame aparecer text=texto_boton, height=25, width=200, command=self.botones[texto_boton] ) boton.grid(row=contador//elementos_fila, column=contador%elementos_fila, padx=5, pady=5) # Incrementa el contador contador += 1 self.root.mainloop()
No te pierdas nada del curso Máster en Python.