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 webbrowserdef 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 acerca():messagebox.showinfo("Acerca de","Demo de menús con Tkinter – 2025")def docs():webbrowser.open_new_tab("https://docs.python.org/3/library/tkinter.html")root=tk.Tk();root.title("Demo menú");root.geometry("500x300")m=tk.Menu(root);root.config(menu=m)fm=tk.Menu(m,tearoff=0);m.add_cascade(label="Archivo",menu=fm)fm.add_command(label="Nuevo",accelerator="Ctrl+N",command=nuevo)fm.add_command(label="Abrir",accelerator="Ctrl+O",command=abrir)fm.add_separator();fm.add_command(label="Guardar",accelerator="Ctrl+S",command=guardar)fm.add_separator();fm.add_command(label="Salir",accelerator="Alt+F4",command=salir)em=tk.Menu(m,tearoff=0);m.add_cascade(label="Edición",menu=em)em.add_command(label="Cortar",accelerator="Ctrl+X",command=lambda:root.focus_get().event_generate("<<Cut>>"))em.add_command(label="Copiar",accelerator="Ctrl+C",command=lambda:root.focus_get().event_generate("<<Copy>>"))em.add_command(label="Pegar",accelerator="Ctrl+V",command=lambda:root.focus_get().event_generate("<<Paste>>"))hm=tk.Menu(m,tearoff=0);m.add_cascade(label="Ayuda",menu=hm)hm.add_command(label="Docs",command=docs);hm.add_separator();hm.add_command(label="Acerca de",command=acerca)root.bind_all("<Control-n>",lambda e:nuevo())root.bind_all("<Control-o>",lambda e:abrir())root.bind_all("<Control-s>",lambda e:guardar())root.bind_all("<Alt-F4>",lambda e:salir())root.bind_all("<Control-x>",lambda e:root.focus_get().event_generate("<<Cut>>"))root.bind_all("<Control-c>",lambda e:root.focus_get().event_generate("<<Copy>>"))root.bind_all("<Control-v>",lambda e:root.focus_get().event_generate("<<Paste>>"))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