Swing y JFC (Java Foundation Classes)

Un men� proporciona una forma de ahorrar espacio y permitir al usuario elegir una entre varias opciones. Otros componentes con los que el usuario puede hacer una elecci�n incluyen combo boxes, lists, radio buttons, y tool bars. Si alguno de los �tems de un men� realiza una acci�n que est� duplicada en otro �tem de men� o en un bot�n de una barra de herramientas, adem�s de esta lecci�n deber�amos leer Como usar Actions.

Los men�s son �nicos en que, por convenci�n, no se sit�an con los otros componentes en el UI. En su lugar, aparecen en una barra de men� o en un men� desplegable. Una barra de men� contiene uno o m�s men�s, y tiene una posici�n dependiente de la plataforma -- normalmente debajo de la parte superior de la ventana. Un men� desplegable es un men� que es invisible hasta que el usuario hace una acci�n del rat�n espec�fica de la plataforma, como pulsar el bot�n derecho del rat�n sobre un componente. Entonces el men� desplegable aparece bajo el cursor.

La siguiente figura muestra los componentes Swing que implementan cada parte de un sistema de men�s.

El resto de esta secci�n nos ense�a los componentes de men� y nos dice c�mo utilizar varias de sus caracter�sticas.

.�La herencia de componentes Men�

Aqu� podemos ver el �rbol de herencia de las clases relacionadas con los men�s.

Como se ve en la figura, los �tems de men�s (incluidos los propios men�s) son simples botones. Podr�amos preguntarnos como un men�, si es s�lo un bot�n, muestra sus �tems. La respuesta es que cuando se activa un men�, autom�ticamente trae un men� desplegable que muestra sus �tems.

.�Crear Men�s

Aqu� est� el c�digo que crea los men�s mostrados al principio de esta p�gina. Puedes encontrar el programa completo en MenuLookDemo.java. Para ejecutarlo, necesitas tener el fichero de imagen: images/middle.gif. Como este c�digo no tiene manejo de eventos, los men�s no hacen nada �til, excepto verse como ser�an. Si ejecutamos el ejemplo, observaremos que a pesar de no tener un manejo de eventos, los men�s y submen�s aparecen cuando deben, y los checkbox y los botones de radio responden apropiadamente cuando el usuario los elige.

//in the constructor for a JFrame subclass:
JMenuBar menuBar;
JMenu menu, submenu;
JMenuItem menuItem;
JCheckBoxMenuItem cbMenuItem;
JRadioButtonMenuItem rbMenuItem;
...
//Create the menu bar.
menuBar = new JMenuBar();
setJMenuBar(menuBar);

//Build the first menu.
menu = new JMenu("A Menu");
menuBar.add(menu);

//a group of JMenuItems
menuItem = new JMenuItem("A text-only menu item");
menu.add(menuItem);
menuItem = new JMenuItem("Both text and icon", 
new ImageIcon("images/middle.gif"));
menu.add(menuItem);
menuItem = new JMenuItem(new ImageIcon("images/middle.gif"));
menu.add(menuItem);

//a group of radio button menu items
menu.addSeparator();
ButtonGroup group = new ButtonGroup();
rbMenuItem = new JRadioButtonMenuItem("A radio button menu item");
rbMenuItem.setSelected(true);
group.add(rbMenuItem);
menu.add(rbMenuItem);
rbMenuItem = new JRadioButtonMenuItem("Another one");
group.add(rbMenuItem);
menu.add(rbMenuItem);

//a group of check box menu items
menu.addSeparator();
cbMenuItem = new JCheckBoxMenuItem("A check box menu item");
menu.add(cbMenuItem);
cbMenuItem = new JCheckBoxMenuItem("Another one");
menu.add(cbMenuItem);

//a submenu
menu.addSeparator();
submenu = new JMenu("A submenu");
menuItem = new JMenuItem("An item in the submenu");
submenu.add(menuItem);
menuItem = new JMenuItem("Another item");
submenu.add(menuItem);
menu.add(submenu);

//Build second menu in the menu bar.
menu = new JMenu("Another Menu");
menuBar.add(menu);

Como se ve en el c�digo, para configurar una barra de men� para un JFrame, se utiliza el m�todo setJMenuBar. Para a�adir un JMenu a un JMenuBar, se utiliza el m�todo add(JMenu). Para a�adir �tems de men� y submen�s a un JMenu, se utiliza el m�todo add(JMenuItem). Estos m�todos y otros m�s se listan en El API de JMenu.

.�Manejar Eventos desde �tems de Men�s

Para detectar cuando el usuario selecciona un JMenuItem, se puede escuchar por eventos action (igual que se har�a para un JButton). Para detectar cuando el usuario selecciona un JRadioButtonMenuItem, se puede escuchar tanto por eventos action, como por eventos item, como se describio en C�mo usar Radio Buttons. Para JCheckBoxMenuItems, generalmente se escuchan eventos de item, como se describi� en C�mo usar CheckBox.

La siguiente figura muestra un programa que a�ade detecci�n de eventos al ejemplo anterior. El c�digo del programa est� en MenuDemo.java. Al igual que MenuLookDemo, MenuDemo utiliza el fichero de imagen images/middle.gif.

Aqu� est� el c�digo que implementa el manejo de eventos.

public class MenuDemo ... implements ActionListener, ItemListener {
    ...
    public MenuDemo() {
        ./for each JMenuItem instance:
        menuItem.addActionListener(this);

        ./for each JRadioButtonMenuItem: 
        rbMenuItem.addActionListener(this);

        ./for each JCheckBoxMenuItem: 
        cbMenuItem.addItemListener(this);
        ...
    }

    public void actionPerformed(ActionEvent e) {
        ./Get information from the action event...
        ./Display it in the text area...
    }

    public void itemStateChanged(ItemEvent e) {
        ./Get information from the item event...
        ./Display it in the text area...
    }

Para ejemplos de manejo de eventos action e item, puedes ver las p�ginas, button, radio button, y check box, as� como la lista de ejemplos al final de esta p�gina.

.�Traer un Men� Desplegable

Para traer un men� desplegable (JPopupMenu), debemos registrar un oyente de rat�n para cada componente al que deber�a estar asociado el men� desplegable. El oyente de mouse debe detectar las peticiones del usuario para que aparezca el men� desplegable. Para las plataformas Windows y Motif, el usuario trae un men� desplegable pulsando el bot�n derecho del rat�n mientras el cursor est� sobre el coponente adecuado.

El oyente de mouse trae un men� desplegable llamando a setVisible(true) sobre el ejemplar apropiado de JPopupMenu. El siguiente c�digo, tomado de PopupMenuDemo.java, muestra c�mo crear y mostrar men�s desplegables.

./where instance variables are declared:
JPopupMenu popup; 

    ./where the GUI is constructed:
    //Create the popup menu.
    popup = new JPopupMenu();
    menuItem = new JMenuItem("A popup menu item");
    menuItem.addActionListener(this);
    popup.add(menuItem);
    menuItem = new JMenuItem("Another popup menu item");
    menuItem.addActionListener(this);
    popup.add(menuItem);

    //Add listener to components that can bring up popup menus.
    MouseListener popupListener = new PopupListener();
    output.addMouseListener(popupListener);
    menuBar.addMouseListener(popupListener);
...
class PopupListener extends MouseAdapter {
    public void mousePressed(MouseEvent e) {
        maybeShowPopup(e);
    }

    public void mouseReleased(MouseEvent e) {
        maybeShowPopup(e);
    }

    private void maybeShowPopup(MouseEvent e) {
        if (e.isPopupTrigger()) {
            popup.show(e.getComponent(),
                       e.getX(), e.getY());
        }
    }
}

Los men�s desplegables tienen unos pocos detalles interesantes de implementaci�n. Uno es que cada men� tiene un men� desplegable apropiado. Cuando el men� se activa, utiliza su men� desplegable para mostrar sus �tems de men�.

Otro detalle es que un propio men� desplegable utiliza otro componente para implementar la ventana que contiene los �tems del men�. Dependiendo de las circunstancias bajo las que se muestre el men� desplegable, podr�a implementar su "ventana" utilizando un componente de peso ligero (como un JPanel), un componente de peso medio (como un Panel), o una ventana de peso pesado (Window).

Las ventanas desplegables de peso ligero son m�s eficientes que las ventanas de peso pesado, pero no funcionan bien si tenemos componentes pesados dentro de nuestro GUI. Especificamente, cuando un �rea de una ventana desplegable de peso ligero se intersecciona con un componente de peso pesado, el componente de peso pesado se dibuja encima. Esta es una de las razones porla que recomendamos no mezclar componentes de peso ligero y de peso pesado. Si realmente necesitamos utilizar un componente de peso pesado en nuestro GUI, podemos utilizar el m�todo setLightWeightPopupEnabled de JPopupMenu para desactivar las ventanas desplegables de peso ligero. Para m�s detalles puedes ver el art�culo Mezclar componentes de peso ligero y pesado, de La conexi�n Swing. (En ingl�s).

.�Personalizar la Distribuci�n de un Men�

Como los men�s se hacen con componentes ordinarios Swing, podemos personalizarlos f�cilmente. Por ejemplo, podemos aa�adir cualquier componente de peso ligero a un JMenu o JMenuBar. Y como JMenuBar utiliza BoxLayout, podemos personalizar la distribuci�n de la barra de men� a�adi�ndole componentes invisibles. Aqu� tienes un ejemplo que a�ade un componente glue a una barra de men�, para que el �ltimo elemento del men� se sit�e en el lado derecho de la barra de men�.

./create and add some menus...
menuBar.add(Box.createHorizontalGlue());
./create the LEFTmost menu...
menuBar.add(LEFTMenu);

Aqu� podemos ver una imagen del resultado, que podemos duplicar compilando y ejecutando MenuGlueDemo.java.

Otra forma de cambiar el aspecto de un men� es cambiar el controlador de distribuci�n que lo controla. Por ejemplo, podemos cambiar el controlador de distribuci�n de la barra de men� del valor por defecto BoxLayout de izquierda-derecha, a algo como un GridLayout. Tambi�n podemos cambiar como un men� activado u otro men� desplegable distribuye sus �tems, como demuestra MenuLayoutDemo.java. Aqu� podmeos ver una imagen de la distribuci�n de men�s que crea MenuLayoutDemo.

.�El API de JMenu

Las siguientes tablas listan los m�todos y constructores m�s utilizados de Jmenu. El API se divide en estas categor�as.

.�Crear y Configurar Barras de Men�

M�todo Prop�sito
JMenuBar() Crea una barra de men�.
void setJMenuBar(JMenuBar)

JMenuBar getJMenuBar()

(en JApplet, JDialog, JFrame, JRootPane)

Selecciona u obtiene la barra de men� de un applet, dialog, frame, o root pane. En las siguientes versiones de Swing y del JDK 1.2, los frames internos tambi�n soportar�n estos m�todos.
void setMenuBar(JMenuBar)

JMenuBar getMenuBar()

(en JInternalFrame)

Selecciona u obtiene la barra de men� de un Frame interno. En las siguientes versiones de Swing y del JDK 1.2, este m�todo ser� anulado y deber�amos utilizar setJMenuBar/getJMenuBar.

.�Crear y Rellenar Men�s

M�todo Prop�sito
JMenu() Crea un men�.
JMenuItem add(JMenuItem)

JMenuItem add(Action)

void add(String)

A�ade un �tem de men� al final del men�. Si el argumento es un objeto Action, el men� crea un �tem de men� como se describe en C�mo usar Actions. Si el argumento es un string, el men� crea autom�ticamente un objeto JMenuItem que muestra el texto especificado.
void addSeparator() A�ade un separador la final del men�.
>JMenuItem insert(JMenuItem, int)

JMenuItem insert(Action, int)

void insert(String, int)

void insertSeparator(int)

Inserta un �tem de men� o un separador en un men�, en la posici�n especificada. El primer �tem de men� es la posici�n 0, el segundo la posici�n 1, etc. Los argumentos JMenuItem, Action, y String se tratan de la misma forma que en los correspondientes m�todos add.
void remove(JMenuItem)

void remove(int)

void removeAll()

Elimina el �tem o �tems especificados del men�. Si el argumento es un entero, especifica la posici�n del �tem a eliminar.

.�Crear y Rellenar Men�s Desplegables

M�todo Prop�sito
JPopupMenu()

JPopupMenu(String)

Crea un men� desplegable. El argumento string opcional especifica el t�tulo que el aspecto y comportamiento podr�a mostrar como parte de la ventana desplegable.
JMenuItem add(JMenuItem)

JMenuItem add(Action)

A�ade un �tem de men� al final del men� desplegable. Si el argumento es un objeto Action, el men� crea un �tem como se describe en C�mo usar Actions.
void addSeparator() A�ade un separador al final del men� desplegable.
void insert(Component, int)

JMenuItem insert(Action, int)

Inserta un �tem de men� en la posici�n especificada. El primer �tem del men� est� en la posici�n 0, el segundo en la posici�n 1, etc. El argumento Component espec�fica el �tem de men� a a�adir. El argumento Action es tratado de la misma forma que en el m�todo add correspondiente.
void remove(JMenuItem)

void remove(int)

void removeAll()

Elimina el �tem o �tems especificados del men�. Si el argumento es un entero, especifica la posici�n del elemento del men� a eliminar.
static void setDefaultLightWeightPopupEnabled(boolean) Por defecto, Swing implementa una ventana de men� utilizando un componente de peso ligero. Esto causa problemas su utilizamos componentes de peso pesado en nuestro programa Swing, como se describi� en Traer un Men� Desplegable. Para evitar estos problemas, se puede llamar a JPopupMenu.

setDefaultLightWeightPopupEnabled(false).

void show(Component, int, int) Muestra el men� desplegable en la posici�n X,Y (especificada en el orden de los argumentos enteros) en el sistema de coordenadas del componente especificado.

.�Implementar �tems de Men�

M�todo Prop�sito
JMenuItem()

JMenuItem(Icon)

JMenuItem(String)

JMenuItem(String, Icon)

JMenuItem(String, int)

Crea un �tem de men� normal. El argumento icon, si existe, especifica el icono que deber�a mostrar el �tem de men�. Igualmente el argumento String, especifica el texto que deber�a mostrar el �tem de men�. El argumento entero especifica el mnem�nico de teclado a utilizar. Se puede especifar una de las constantes VK definidas en la clase KeyEvent. Por ejemplo, para especificar "a" como el mnem�nico, podemos utilizar KeyEvent.VK_A.
JCheckBoxMenuItem()

JCheckBoxMenuItem(Icon)

JCheckBoxMenuItem(String)

JCheckBoxMenuItem(String, Icon)

JCheckBoxMenuItem(String, boolean)

JCheckBoxMenuItem(String, Icon, boolean)

Crea un �tem de men� que se parece y act�a como un checkbox. Si se especifica un icono, el �tem de men� utiliza el icono en vez del icono por defecto de los checkboxes. El argumento string, si existe, especifica el texto que deber�a mostrar el �tem de men�. Si se especifica true para el argumento booleano, el �tem de men� estar� inicialmente seleccionado. De lo contario el �ten de men� est� desactivado.
JRadioButtonMenuItem()

JRadioButtonMenuItem(Icon)

JRadioButtonMenuItem(String)

JRadioButtonMenuItem(String, Icon)

Crea un �tem de men� que se parece y act�a como un radio buttom. Si se especifica un icono, el �tem de men� utiliza el icono en vez del icono por defecto de los botones de radio. El argumento string, si existe, especifica el texto que deber�a mostrar el �tem de men�. El �tem de men� est� inicialmente desactivado.
void setState(boolean)

boolean getState()

Seleciona u obtiene el estado de selecci�n de un �tem de men�.
void setEnabled(boolean) Si el argumento es true, activa el �tem de men�, si es false lo desactiva.
void setMnemonic(char) Selecciona la tecla alternativa para seleccionar el �tem de men� sin el rat�n.
void setActionCommand(String) Seleciona el nombre de la acci�n realizada por el �tem de men�.
void addActionListener(ActionListener)

void addItemListener(ItemListener)

A�ade un oyente de eventos al �tem de men�. Puedes ver Manejar Eventos desde �tems de Men�s para m�s detalles.
La mayor�a de los m�todos anteriores son heredados desde AbstractButton. Puedes ver El API Button para m�s informaci�n sobre otros m�todos �tiles proporcionados por AbstractButton.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR