IronPython - Menú del Formulario (Form.Menu)



Introducción


Los formularios de las aplicaciones de escritorio frecuentemente muestran un menú en la parte superior, justo debajo de la caja de control (donde están los botones minimizar, maximizar y cerrar).

Para añadir un menú a un Form hay que asignar una instancia de MainMenu a la propiedad Form.Menu:

# -*- coding: utf-8 -*-

import sys, clr

for reference in 'System.Windows.Forms', 'System.Drawing':
    clr.AddReference(reference)

from System.Windows.Forms import *
from System.Drawing import *

form = Form()
form.Text = 'App'
form.Icon = Icon.ExtractAssociatedIcon(sys.executable)

# ASIGNAR MENÚ PARA EL FORMULARIO
form.Menu = MainMenu()

Application.EnableVisualStyles()
Application.Run(form)

Si ejecutas este script aparece un formulario vacío. No se muestra ningún menú porque todavía no hemos añadido ningún item a este.



Añadir Items al Menú (botones)


Los items de un MainMenu son botones que pueden responder a eventos. Puedes crear un MenuItem y añadirlo a un MainMenu:

menu = form.Menu = MainMenu()

item = MenuItem()
item.Text = 'Item del Menú'

menu.MenuItems.Add(item)

MainMenu - 1 Item

Muchas aplicaciones muestras en su menú los botones Abrir, Guardar y Cerrar. Vamos a implementar estos items:

menu = form.Menu = MainMenu()

abrir, guardar, cerrar = MenuItem(), MenuItem(), MenuItem()
abrir.Text, guardar.Text, cerrar.Text = 'Abrir', 'Guardar', 'Cerrar'

for item in abrir, guardar, cerrar:
    menu.MenuItems.Add(item)

MainMenu - 3 Items

Estos items / botones todavía no hacen nada, pero podemos manejar su evento Click. Por ejemplo, vamos a hacer que cada uno de ellos muestre un MessageBox:

def show_msg(sender, e):
    MessageBox.Show('Quieres {} un archivo'.format(sender.Text), sender.Text)

# ...

menu = form.Menu = MainMenu()

abrir, guardar, cerrar = MenuItem(), MenuItem(), MenuItem()
abrir.Text, guardar.Text, cerrar.Text = 'Abrir', 'Guardar', 'Cerrar'

for item in abrir, guardar, cerrar:
    item.Click += show_msg  # <--- ATENCIÓN!
    menu.MenuItems.Add(item)

MainMenu - Item Abrir - Click



Añadir Items a los Items del Menú


Al igual que pueden añadirse items al MainMenu utilizadno MainMenu.MenuItems.Add, puedes añadir items a los MenuItems utilizando MenuItem.MenuItems.Add.

Por ejemplo, vamos a hacer que el MainMenu tengda dos items, uno con el texto "Archivo" y otro con el texto "Ayuda".

menu = form.Menu = MainMenu()

archivo, ayuda = MenuItem(), MenuItem()
archivo.Text, ayuda.Text = 'Archivo', 'Ayuda'
ayuda.Click += lambda *args: MessageBox.Show('No hay Ayuda disponible', 'Ayuda', MessageBoxButtons.OK, MessageBoxIcon.Information)

for item in archivo, ayuda:
    menu.MenuItems.Add(item)

MainMenu - Items Archivo y Ayuda

Al hacer click en ayuda se muestra un MessageBox, y al hacer click en archivo no sucede nada.

A continuación vamos a añadir los botones Ayuda, Guardar y Cerrar, pero esta vez estarán dentro de archivo:

def show_msg(sender, e):
    MessageBox.Show('Quieres {} un archivo'.format(sender.Text), sender.Text)

# ...

abrir, guardar, cerrar = MenuItem(), MenuItem(), MenuItem()
abrir.Text, guardar.Text, cerrar.Text = 'Abrir', 'Guardar', 'Cerrar'

for item in abrir, guardar, cerrar:
    item.Click += show_msg
    archivo.MenuItems.Add(item) # Los añadimos al item "archivo", no al menú

MainMenu con submenú

El código quedaría así:

def show_msg(sender, e):
    MessageBox.Show('Quieres {} un archivo'.format(sender.Text), sender.Text)

form = Form()
form.Text = 'App'
form.Icon = Icon.ExtractAssociatedIcon(sys.executable)

menu = form.Menu = MainMenu()

archivo, ayuda = MenuItem(), MenuItem()
archivo.Text, ayuda.Text = 'Archivo', 'Ayuda'
ayuda.Click += lambda *args: MessageBox.Show('No hay Ayuda disponible', 'Ayuda', MessageBoxButtons.OK, MessageBoxIcon.Information)

for item in archivo, ayuda:
    menu.MenuItems.Add(item)

abrir, guardar, cerrar = MenuItem(), MenuItem(), MenuItem()
abrir.Text, guardar.Text, cerrar.Text = 'Abrir', 'Guardar', 'Cerrar'

for item in abrir, guardar, cerrar:
    item.Click += show_msg
    archivo.MenuItems.Add(item)

Para no escribir tantas veces MenuItem() puedes utilizar listas de compresión. El código completo del script quedaría así:

# -*- coding: utf-8 -*-

import sys, clr

for reference in 'System.Windows.Forms', 'System.Drawing':
    clr.AddReference(reference)

from System.Windows.Forms import *
from System.Drawing import *


def show_msg(sender, e):
    MessageBox.Show('Quieres {} un archivo'.format(sender.Text), sender.Text)

form = Form()
form.Text = 'App'
form.Icon = Icon.ExtractAssociatedIcon(sys.executable)

menu = form.Menu = MainMenu()

archivo, ayuda, abrir, guardar, cerrar = [i() for i in [MenuItem] * 5]     # <----- ATENCIÓN!
archivo.Text, ayuda.Text = 'Archivo', 'Ayuda'
abrir.Text, guardar.Text, cerrar.Text = 'Abrir', 'Guardar', 'Cerrar'

ayuda.Click += lambda *args: MessageBox.Show('No hay Ayuda disponible', 'Ayuda', MessageBoxButtons.OK, MessageBoxIcon.Information)

for item in archivo, ayuda:
    menu.MenuItems.Add(item)

for item in abrir, guardar, cerrar:
    item.Click += show_msg
    archivo.MenuItems.Add(item)


Application.EnableVisualStyles()
Application.Run(form)


Para hacer una implementación realista de los botones "Abrir" y "Cerrar" habría que utilizar OpenFileDialog y SaveFileDialog.
Echa un vistazo a la sección Diálogos de selección.