Crear menús profesionales en Tkinter (File, Edit, Help…)
Introducción
Tkinter es la biblioteca estándar de interfaces gráficas en Python. Una barra de menú bien estructurada mejora la usabilidad y le da a tu aplicación un aspecto profesional. En este artículo veremos cómo:
- Crear la barra de
Menuy sus sub‑menús (Archivo, Edición, Ayuda). - Asociar funciones a cada ítem y usar separadores.
- Definir atajos de teclado (por ejemplo Ctrl+N y Ctrl+S).
- Aplicar buenas prácticas de mantenimiento, compatibilidad y rendimiento.
1. Estructura básica del menú
El widget Menu se ancla a la ventana principal mediante el método config(menu=menu_bar). Cada sub‑menú es a su vez un Menu con la opción tearoff=0 para evitar la línea de separación “desprendible”.
import tkinter as tk
root = tk.Tk()
root.title("Ejemplo de menú")
# Barra de menú principal
menu_bar = tk.Menu(root)
root.config(menu=menu_bar)
2. Sub‑menú Archivo con separadores y atajos
Los atajos se añaden mediante la opción accelerator (solo visual) y vinculando la combinación con bind_all o bind_class para que funcione en cualquier widget.
def nuevo():
print("Nuevo documento")
def abrir():
print("Abrir archivo")
def guardar():
print("Guardar archivo")
def salir():
root.quit()
file_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Archivo", menu=file_menu)
file_menu.add_command(label="Nuevo", accelerator="Ctrl+N", command=nuevo)
file_menu.add_command(label="Abrir…", accelerator="Ctrl+O", command=abrir)
file_menu.add_separator()
file_menu.add_command(label="Guardar", accelerator="Ctrl+S", command=guardar)
file_menu.add_separator()
file_menu.add_command(label="Salir", accelerator="Alt+F4", command=salir)
# Vinculación de atajos
root.bind_all("", lambda e: nuevo())
root.bind_all("", lambda e: abrir())
root.bind_all("", lambda e: guardar())
root.bind_all("", lambda e: salir())
3. Sub‑menú Edición (opcional)
En aplicaciones más complejas se añaden comandos como Cortar, Copiar y Pegar. Tkinter ya incluye atajos por defecto, pero podemos reforzarlos.
edit_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Edición", menu=edit_menu)
edit_menu.add_command(label="Cortar", accelerator="Ctrl+X", command=lambda: root.focus_get().event_generate('<>'))
edit_menu.add_command(label="Copiar", accelerator="Ctrl+C", command=lambda: root.focus_get().event_generate('<>'))
edit_menu.add_command(label="Pegar", accelerator="Ctrl+V", command=lambda: root.focus_get().event_generate('<>'))
root.bind_all('', lambda e: root.focus_get().event_generate('<>'))
root.bind_all('', lambda e: root.focus_get().event_generate('<>'))
root.bind_all('', lambda e: root.focus_get().event_generate('<>'))
4. Sub‑menú Ayuda con enlaces externos
Los ítems de ayuda suelen abrir diálogos o lanzar el navegador web.
import webbrowser
def mostrar_acerca():
tk.messagebox.showinfo("Acerca de", "Aplicación demo – Tkinter 2025")
def abrir_documentacion():
webbrowser.open_new_tab('https://docs.python.org/3/library/tkinter.html')
help_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Ayuda", menu=help_menu)
help_menu.add_command(label="Documentación", command=abrir_documentacion)
help_menu.add_separator()
help_menu.add_command(label="Acerca de…", command=mostrar_acerca)
5. Buenas prácticas y consideraciones avanzadas
Compatibilidad y estilos
- En macOS, los menús aparecen en la barra del sistema. Usa
root.createcommandsi necesitas adaptar atajos. - Para un look native en Windows, evita
ttk.Styleen los menús; Tkinter ya respeta el tema del SO. - Si la aplicación será empaquetada con
PyInstaller, verifica que los recursos (iconos, archivos .ico) estén incluidos en elspec.
Rendimiento y escalabilidad
- Los menús se crean una sola vez; evita recrearlos en callbacks para reducir overhead.
- En interfaces con cientos de comandos, considera lazy loading (cargar sub‑menús al abrirlos).
- Utiliza
menu.entryconfig(index, state='disabled')para desactivar temporalmente opciones costosas.
6. Solución de problemas frecuente
- Los atajos no funcionan en algunos widgets. Asegúrate de usar
bind_allobind_class('Text')según el widget objetivo. - Separadores aparecen como líneas gruesas. En versiones antiguas de Tk, el estilo se controla con la variable de entorno
TCL_LIBRARY. Actualiza a Tk 8.6+. - El menú desaparece al maximizar la ventana. Verifica que no estés llamando a
root.geometry()después deconfig(menu=…).
7. Ejemplo completo listo para ejecutar
import tkinter as tk
from tkinter import messagebox
import webbrowser
# ---------------------------------------------------
# Funciones de los ítems del menú
# ---------------------------------------------------
def nuevo():
messagebox.showinfo("Nuevo", "Crear un nuevo documento")
def abrir():
messagebox.showinfo("Abrir", "Abrir archivo existente")
def guardar():
messagebox.showinfo("Guardar", "Guardar documento actual")
def salir():
root.quit()
def mostrar_acerca():
messagebox.showinfo("Acerca de", "Demo de menús con Tkinter – 2025")
def abrir_documentacion():
webbrowser.open_new_tab('https://docs.python.org/3/library/tkinter.html')
# ---------------------------------------------------
# Configuración de la ventana principal
# ---------------------------------------------------
root = tk.Tk()
root.title("Demo de barra de menú")
root.geometry("500x300")
# ---------------------------------------------------
# Creación de la barra de menú
# ---------------------------------------------------
menu_bar = tk.Menu(root)
root.config(menu=menu_bar)
# Archivo
file_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Archivo", menu=file_menu)
file_menu.add_command(label="Nuevo", accelerator="Ctrl+N", command=nuevo)
file_menu.add_command(label="Abrir…", accelerator="Ctrl+O", command=abrir)
file_menu.add_separator()
file_menu.add_command(label="Guardar", accelerator="Ctrl+S", command=guardar)
file_menu.add_separator()
file_menu.add_command(label="Salir", accelerator="Alt+F4", command=salir)
# Edición (opcional)
edit_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Edición", menu=edit_menu)
edit_menu.add_command(label="Cortar", accelerator="Ctrl+X", command=lambda: root.focus_get().event_generate('<>'))
edit_menu.add_command(label="Copiar", accelerator="Ctrl+C", command=lambda: root.focus_get().event_generate('<>'))
edit_menu.add_command(label="Pegar", accelerator="Ctrl+V", command=lambda: root.focus_get().event_generate('<>'))
# Ayuda
help_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Ayuda", menu=help_menu)
help_menu.add_command(label="Documentación", command=abrir_documentacion)
help_menu.add_separator()
help_menu.add_command(label="Acerca de…", command=mostrar_acerca)
# ---------------------------------------------------
# Atajos de teclado (globales)
# ---------------------------------------------------
root.bind_all('', lambda e: nuevo())
root.bind_all('', lambda e: abrir())
root.bind_all('', lambda e: guardar())
root.bind_all('', lambda e: salir())
root.bind_all('', lambda e: root.focus_get().event_generate('<>'))
root.bind_all('', lambda e: root.focus_get().event_generate('<>'))
root.bind_all('', lambda e: root.focus_get().event_generate('<>'))
# ---------------------------------------------------
# Main loop
# ---------------------------------------------------
root.mainloop()
Ejecuta este script y observa cómo los menús y los atajos funcionan en Windows, macOS y Linux sin cambios.
9 Crear menús profesionales en Tkinter (File, Edit, Help…) – Guía completa