DMarlon Studio

Lección 9 · 9 de 20

La barra de menús · tkinter

Cree la barra de menús de una ventana de tkinter con tk.Menu: menús en cascada, separadores, atajos, casillas y opciones de radio.

tkinter · La barra de menús en DMarlon Studio: el código del ejemplo y la ventana que abre al ejecutarlo

La barra es un tk.Menu que se pone en la ventana con root.config(menu=bar). Cada menú desplegable es otro tk.Menu que se cuelga de ella con add_cascade(label="File", menu=file). tearoff=0 quita la línea discontinua que, en Windows y Linux, permite arrancar el menú a una ventanita.

Dentro van las opciones: add_command (una orden; command= es la función que ejecuta), add_separator (una raya) y dos tipos con estado: add_checkbutton, que se activa y desactiva unido a una BooleanVar, y add_radiobutton, una entre varias que comparten la misma StringVar (queda marcada la del valor actual, 100%).

accelerator="Ctrl+N" solo escribe el atajo junto a la opción; para que la tecla funcione hace falta root.bind("<Control-n>", ...). Por eso el ejemplo hace las dos cosas.

En macOS la barra no está dentro de la ventana sino arriba de la pantalla, así que el ejemplo recorre los menús y los escribe en un Text: index("end") da el último índice, type(i) el tipo de cada entrada y entrycget(i, "label") su texto.

En DMarlon Studio es el Menú de la paleta: escribe las opciones en el inspector, con submenús y separadores, y el estudio genera el tk.Menu con sus cascadas y lo pone en la ventana; cada opción llama a un método con su ruta.

Código · main.py

import tkinter as tkfrom tkinter import ttkroot = tk.Tk()root.title("Editor")root.geometry("460x300")wrap, zoom = tk.BooleanVar(value=True), tk.StringVar(value="100%")# The bar is a Menu; each cascade opens another Menu (tearoff=0: no dashed line).bar = tk.Menu(root)file = tk.Menu(bar, tearoff=0)file.add_command(label="New", accelerator="Ctrl+N", command=lambda: print("New"))file.add_command(label="Open…", accelerator="Ctrl+O")file.add_separator()file.add_command(label="Quit", command=root.destroy)view = tk.Menu(bar, tearoff=0)view.add_checkbutton(label="Word wrap", variable=wrap)   # on / offfor size in ("75%", "100%", "150%"):                      # one of several    view.add_radiobutton(label=f"Zoom {size}", variable=zoom, value=size)root.bind("<Control-n>", lambda e: print("New"))  # accelerator is only the text# On macOS the bar sits at the top of the screen: list it in the window too.ttk.Label(root, text=f"Word wrap = {wrap.get()}, zoom = {zoom.get()}").pack(side="bottom", pady=8)listing = tk.Text(root, bg="white", fg="black", font=("Menlo", 12), padx=12, pady=10)listing.pack(fill="both", expand=True)for title, menu in (("File", file), ("View", view)):    bar.add_cascade(label=title, menu=menu)    listing.insert("end", f"{title}\n")    for i in range(menu.index("end") + 1):        sep = menu.type(i) == "separator"        label, keys = ("─" * 12, "") if sep else (menu.entrycget(i, "label"), menu.entrycget(i, "accelerator"))        listing.insert("end", f"   {label:<14}{keys:<8}{menu.type(i)}\n")root.config(menu=bar)root.mainloop()

Para recordar

  • root.config(menu=bar) pone la barra en la ventana.
  • add_cascade cuelga un menú y add_command añade una orden.
  • add_checkbutton y add_radiobutton guardan su estado en variables.
  • accelerator es solo texto: el atajo necesita bind.

Ejercicio

Añada un menú «Help» con la opción «About» que escriba un mensaje con print, y haga que Ctrl+O también funcione.