Download Manejo básico de Menús
Document related concepts
no text concepts found
Transcript
Menús No hay ningún método para diseñar un buen interfaz de usuario, todo depende del programador. Los Menús son siempre el centro de la aplicación, porque son el medio de que el usuario interactúe con esa aplicación. La diferencia entre una aplicación útil y otra que es totalmente frustrante radica en la organización de los menús, pero eso, las reglas del diseño de un buen árbol de menús, no están claras. Así que, se va a explicar lo básico, sin que se deba tomar como dogma de fe, para que luego cada uno haga lo que mejor le parezca. En Java, la jerarquía de clases que intervienen en la construcción y manipulación de menús es la que se muestra en la lista siguiente: java.lang.Object MenuShorcut java.awt.MenuComponent java.awt.MenuBar java.awt.MenuItem java.awt.Menu java.awt.CheckboxMenuItem java.awt.PopMenu MenuComponent, es la superclase de todos los Componentes relacionados con menús. MenuShortcut, representa el acelerador de teclado, o la combinación de teclas rápidas, para acceder a un MenuItem. MenuItem, representa una opción en un menú. Menu, es un Componente de una barra de menú. MenuBar, encapsula el concepto de una barra de menú en un Frame. PopupMenu, implementa un menú que puede ser presentado dinámicamente dentro de un Componente. CheckboxMenuItem, genera una caja de selección que representa una opción en un menú. A continuación se exploran una a una las clases que se acaban de citar. Clase MenuComponent Esta clase no contiene campos, solamente tiene un constructor y dispone de una docena de métodos que están accesibles a todas sus subclases. Clase Menu Esta es la clase que se utiliza para construir los menús que se manejan habitualmente, conocidos como menús de persiana (o pull-down). Dispone de varios constructores para poder, entre otras cosas, crear los menús con o sin etiqueta. No tiene campos y proporciona varios métodos que se pueden utilizar para crear y mantener los menús en tiempo de ejecución. En el programa de ejemplo java1317.java, se usarán algunos de ellos. Constructores: new Menu(); new Menu(“etiqueta”); new Menu(“etiqueta”, boolean); // true se vuelve flotante el menú, false permanece fijo en la barra Métodos: add(obj MenuItem); add(obj CheckboxMenuItem); add(obj Menu); // el menú añadido se convierte en submenú addSeparator();// agrega una línea divisora entre las opciones del menú getItem();// regresa el objeto MenuItem correspondiente a la opción seleccionada getItemCount();// regresa el número de elementos de ese menú insert(obj MenuItem, posicion); // inserta la opción en el menú en la posición especificada Clase MenuItem Esta clase se emplea para instanciar los objetos que constituirán los elementos seleccionables del menú. Kena Puga Nathal Página 1 09/08/2017 1 Constructores; new MenuItem(); new MenuItem(“etiqueta”); new MenuItem( “etiqueta”, obj MenuShortcut ); Metodos: addActionListener( ActionListener ); setEnabled( boolean); //true habilita la opción isEnabled(); // regresa true si esta habilitada la opción setLabel(“etiqueta”); // poner o cambiar etiqueta de la opción getLabel(); // regresa una cadena que representa la etiqueta de la opción setShortcut(obj MenuShortcut); getShortcut(); // regresa un objeto de la clase MenuShortcut Cuando se selecciona una opción de un menú, bien a través del ratón o por la combinación rápida de teclas, se genera un evento de tipo ActionEvent. Para que la selección de la opción en un menú ejecute una determinada acción, se ha de instanciar y registrar un objeto ActionListener que contenga el método actionPerformed() sobreescrito para producir la acción deseada. En el ejemplo java1317.java, solamente se presenta en pantalla la identificación de la opción de menú que se ha seleccionado; en un programa realmente útil, la acción seguramente que deberá realizar algo más interesante que eso. Clase MenuShortcut Esta clase se utiliza para instanciar un objeto que representa un acelerador de teclado, o una combinación de teclas rápidas, para un determinado MenuItem. Aparentemente, casi todas las teclas rápidas consisten en mantener pulsada la tecla Control a la vez que se pulsa cualquier otra tecla. Constructores: MenuShortcut(int); //virtual keyCode proporcionado por la clase KeyEvent MenuShortcut(int, boolean ); //true agrega shift, false solo control + tecla KeyEvent.VK_tecla Dispone de un segundo parámetro que indica si el usuario ha de mantener también pulsada la tecla de cambio a mayúsculas (Shift). El primer parámetro es el código de la tecla, que es el mismo que se devuelve en el campo keyCode del evento KeyEvent, cuando se pulsa una tecla. La clase KeyEvent define varias constantes simbólicas para estos códigos de teclas, como son: VK_8, VK_9, VK_A, VK_B. Letras: VK_A a la VK_Z Dígitos: VK_0 a la VK_9 Funciones: VK_F1 a la VK_F12 Especiales: VK_ALT, VK_ALT_GRAPH, VK_BACK_SLASH, VK_SLASH, .., Para mayor información consultar la clase KeyEvent en el API de java. Podemos crear de dos maneras los objetos: MenuShortcut ms = new MenuShortcut(KeyEvent.VK_A, false); o alternativamente MenuShortcut ms = new MenuShortcut(KeyEvent.getExtendedKeyCodeForChar('A'), false); Clase MenuBar Sólo tiene un constructor público, y es la clase que representa el concepto que todo usuario tiene de la barra de menú que está presente en la mayoría de las aplicaciones gráficas basadas en ventanas. Constructor: new MenuBar(); Métodos: add(obj Menu); getMenuCount(); //regresa la cantidad de menús asociados a esa barra de menús Kena Puga Nathal Página 2 09/08/2017 2 En el programa java1317.java, ilustra algunos de los aspectos que intervienen en los menús. Es una aplicación que coloca dos menús sobre un objeto Frame. Uno de los menús tiene dos opciones y el otro, tres. La primera opción del primer menú también tiene asignada una combinación de teclas rápidas: Ctrl+Shift+K. Cuando se selecciona un elemento del menú, éste genera un evento de tipo ActionEvent, que presenta una línea de texto en pantalla indicando cuál ha sido el elemento del menú que se ha seleccionado, por ejemplo: % java java1317 java.awt.MenuItem[menuitem0,label=Primer Elemento del Menu A, shortcut=Ctrl+Shift+K] java.awt.MenuItem[menuitem1,label=Segundo Elemento del Menu A] java.awt.MenuItem[menuitem0,label=Primer Elemento del Menu A, shortcut=Ctrl+Shift+K] java.awt.MenuItem[menuitem3,label=Segundo Elemento del Menu B] También se instancia y registra un objeto receptor de eventos windowClosing() para terminar la ejecución del programa cuando se cierra el Frame. import java.awt.*; import java.awt.event.*; public class java1317 { public static void main(String args[]){ IHM ihm = new IHM(); } } class IHM { public IHM() { // Se instancia un objeto de tipo Acelerador de Teclado MenuShortcut miAcelerador = new MenuShortcut( KeyEvent.VK_K,true ); // Se instancian varios objetos de tipo Elementos de Menu MenuItem primerElementoDeA = new MenuItem("Primer Elemento del Menu A",miAcelerador ); MenuItem segundoElementoDeA = new MenuItem("Segundo Elemento del Menu A" ); MenuItem primerElementoDeB = new MenuItem("Primer Elemento del Menu B" ); MenuItem segundoElementoDeB = new MenuItem("Segundo Elemento del Menu B" ); MenuItem tercerElementoDeB = new MenuItem("Tercer Elemento del Menu B" ); // Se instancia un objeto ActionListener y se registra sobre los // objetos MenuItem primerElementoDeA.addActionListener( new MiGestorDeMenu() ); segundoElementoDeA.addActionListener( new MiGestorDeMenu() ); primerElementoDeB.addActionListener( new MiGestorDeMenu() ); segundoElementoDeB.addActionListener( new MiGestorDeMenu() ); tercerElementoDeB.addActionListener( new MiGestorDeMenu() ); // Se instancian dos objetos de tipo Menu y se les añaden los // objetos MenuItem Menu menuA = new Menu( "Menu A" ); menuA.add( primerElementoDeA ); menuA.add( segundoElementoDeA ); Menu menuB = new Menu( "Menu B" ); menuB.add( primerElementoDeB ); menuB.add( segundoElementoDeB ); menuB.add( tercerElementoDeB ); Kena Puga Nathal Página 3 09/08/2017 3 // Se instancia una Barra de Menu y se le añaden los Menus MenuBar menuBar = new MenuBar(); menuBar.add( menuA ); menuBar.add( menuB ); // Se instancia un objeto Frame y se le asocia el objeto MenuBar. // Observese que esta no es la tipico invocacion del metodo // miFrame.add(), sino que es una forma especial de invocar // al metodo necesaria para poder asociar un objeto Barra de Menu // a un objeto Frame Frame miFrame = new Frame( "Tutorial de Java, AWT" ); // Esto no es el metodo add(), como se podria esperar miFrame.setMenuBar( menuBar ); miFrame.setSize( 250,100 ); miFrame.setVisible( true ); // Se instancia y registra un receptor de eventos de ventana para // concluir el programa cuando se cierre el Farme miFrame.addWindowListener( new Conclusion() ); } } // Clase para instanciar un objeto ActionListener que se registra // sobre los elementos del menu class MiGestorDeMenu implements ActionListener { public void actionPerformed( ActionEvent evt ) { // Presenta en pantalla el elemento que ha generado el evento // de tipo Action System.out.println( evt.getSource() ); } } class Conclusion extends WindowAdapter { public void windowClosing( WindowEvent evt ) { System.exit( 0 ); } } A continuación se revisan los fragmentos de código más interesantes del ejemplo, aunque en el programa se puede observar que hay gran cantidad de código repetitivo, ya que esencialmente se necesitan las mismas sentencias para crear cada opción del menú y registrar un objeto receptor de eventos sobre cada una de ellas. El programa genera dos menús separados con el mismo código básicamente. Quizá lo más interesante no sea el código en sí mismo, sino el orden en que se realizan los diferentes pasos de la construcción del menú. La primera sentencia que merece la pena es la que instancia un objeto MenuShortcut, que se utilizará posteriormente en la instanciación de un objeto MenuItem. MenuShortcut miAcelerador = new MenuShortcut( KeyEvent.VK_K,true ); La lista de argumentos del constructor especifica la combinación de teclas que se van a utilizar y el parámetro true, indica que es necesaria la tecla del cambio a mayúsculas (Shift) pulsada. El primer parámetro es la constante simbólica que la clase KeyEvent define para la tecla K y, aparentemente, la tecla Control siempre debe estar pulsada en este tipo de combinaciones para ser utilizadas las teclas normales como aceleradores de teclado. Cuando se utiliza este constructor, en el menú aparecerá la etiqueta asignada y a su derecha, la combinación de teclas alternativas para activarla directamente. Kena Puga Nathal Página 4 09/08/2017 4 El siguiente fragmento de código que se puede ver es el típico de instanciación de objetos MenuItem, que posteriormente se añadirán al objeto Menu para crear el menú. Se muestran dos tipos de instrucciones, el primer estilo especifica un acelerador de teclado y el segundo no. MenuItem primerElementoDeA = new MenuItem("Primer Elemento del Menu A",miAcelerador ); MenuItem segundoElementoDeA = new MenuItem("Segundo Elemento del Menu A" ); Ahora se encuentra el código que instancia y registra un objeto ActionListener sobre la opción del menú, tal como se ha visto en ejemplos anteriores. Aquí solamente se incluye para ilustrar el hecho de que la asociación de objetos ActionListener con opciones de un menú, no difiere en absoluto de la asociación de objetos ActionListener con objetos Button, o cualquier otro tipo de objeto capaz de generar eventos de tipo ActionEvent. primerElementoDeA.addActionListener( new MiGestorDeMenu() ); Las sentencias que siguen son las ya vistas, y que aquí se emplean para instanciar cada uno de los dos objetos Menu y añadirles las opciones existentes. Es la típica llamada al método Objeto.add() que se ha utilizado en programas anteriores. Menu menuA = new Menu( "Menu A" ); menuA.add( primerElementoDeA ); El siguiente fragmento de código instancia un objeto MenuBar y le añade los dos menús que se han definido antes. MenuBar menuBar = new MenuBar(); menuBar.add( menuA ); menuBar.add( menuB ); En este momento ya están creados los dos objetos Menu y colocados en un objeto MenuBar. Sin embargo, no se ha dicho nada sobre el ensamblamiento del conjunto. Esto se hace en el momento de asociar el objeto MenuBar con el objeto Frame. En este caso no se puede utilizar el método add(), sino que se tiene que invocar a un método especial de la clase Frame que tiene la siguiente declaración: public synchronized void setMenuBar( MenuBar mb ) y en este caso concreto se hace en las sentencias que se reproducen seguidamente: Frame miFrame = new Frame( "Tutorial de Java, AWT" ); // Esto no es el metodo add(), como se podria esperar miFrame.setMenuBar( menuBar ); Y hasta aquí lo más interesante del ejemplo, porque el código que resta es similar al que ya se ha visto y descrito en otros ejemplos del Tutorial, y que el lector se habrá encontrado si ha seguido la lectura secuencialmente. Clase CheckboxMenuItem Esta clase se utiliza para instanciar objetos que puedan utilizarse como opciones en un menú. Al contrario que las opciones de menú que se han visto al hablar de objetos MenuItem, estas opciones tienen mucho más parentesco con las cajas de selección, tal como se podrá comprobar a lo largo del ejemplo java1318.java. Esta clase proporciona tres constructores públicos, en donde se puede especificar el texto de la opción y el estado en que se encuentra. Si no se indica nada, la opción estará deseleccionada, aunque hay un constructor que permite indicar en un parámetro de tipo booleano, que la opción se encuentra seleccionada, o marcada, indicando true en ese valor. Constructores: new CheckboxMenuItem(); new CheckboxMenuItem(“etiqueta”); new CheckboxMenuItem(“etiqueta”, boolean); //true seleccionada la opción por omisión Métodos: Kena Puga Nathal Página 5 09/08/2017 5 addItemListener( ItemListener ); getState(); //regresa true si esa opción esta seleccionada setState(boolean); // true selecciona la opción Cuando se selecciona una opción del menú, se genera un evento de tipo ItemEvent. Para que se produzca la acción que se desea con esa selección, es necesario instanciar y registrar un objeto ItemListener que contenga el método itemStateChanged() sobrescrito con la acción que se quiere. Por ejemplo, en el programa que se presenta a continuación, la acción consistirá en presentar la identificación y estado de la opción de menú que se haya seleccionado. Cuando se ejecuta el programa java1318.java, aparece un menú sobre un objeto Frame. El menú contiene tres opciones de tipo CheckboxMenuItem. Una opción de este tipo es semejante a cualquier otra, hasta que se selecciona. Cuando se seleccione, aparecerá una marca, o cualquier otra identificación visual, para saber que esa opción está seleccionada. Estas acciones hacen que el estado de la opción cambie, y ese estado se puede conocer a través del método getState(). Cuando se selecciona una opción, se genera un evento de tipo ItemEvent, que contiene información del nuevo estado, del texto de la opción y del nombre asignado a la opción. Estos datos pueden utilizarse para identificar cuál de las opciones ha cambiado y, también, para implementar la acción requerida que, en este caso del ejemplo siguiente, consiste en presentar una línea de texto en la pantalla con la información que contiene el objeto ItemEvent, más o menos semejante a la que se reproduce a continuación: % java java1318 java.awt.CheckboxMenuItem[chkmenuitem0,label=Primer Elemento,state=true] java.awt.CheckboxMenuItem[chkmenuitem2,label=Terecer Elemento,state=true] java.awt.CheckboxMenuItem[chkmenuitem0,label=Primer Elemento,state=false] java.awt.CheckboxMenuItem[chkmenuitem1,label=Segundo Elemento,state=true] java.awt.CheckboxMenuItem[chkmenuitem0,label=Primer Elemento,state=true] Como siempre, se instancia y registra sobre el Frame un objeto receptor de eventos windowClosing() para la conclusión del programa cuando se cierre el Frame. import java.awt.*; import java.awt.event.*; public class java1318 { public static void main( String args[] ) { IHM ihm = new IHM(); } } class IHM { public IHM() { // Instancia objetos de tipo CheckboxMenuItem CheckboxMenuItem primerElementoMenu = new CheckboxMenuItem( "Primer Elemento" ); CheckboxMenuItem segundoElementoMenu = new CheckboxMenuItem( "Segundo Elemento" ); CheckboxMenuItem tercerElementoMenu = new CheckboxMenuItem( "Tercer Elemento" ); // Instancia un objeto ItemListener y lo registra sobre los // objetos CheckboxMenuItem, elementos del menu de seleccion primerElementoMenu.addItemListener( new ControladorCheckBox() ); segundoElementoMenu.addItemListener( new ControladorCheckBox() ); tercerElementoMenu.addItemListener( new ControladorCheckBox() ); Kena Puga Nathal Página 6 09/08/2017 6 // Instancia un objeto Menu y le añade los botones de la caja // de seleccion Menu menuA = new Menu( "Menu A" ); menuA.add( primerElementoMenu ); menuA.add( segundoElementoMenu ); menuA.add( tercerElementoMenu ); // Instancia un objeto MenuBar y le añade el objeto Menu MenuBar barraMenu = new MenuBar(); barraMenu.add( menuA ); // Se instancia un objeto Frame y se le asocia el objeto MenuBar. // Observese que esta no es la tipico invocacion del metodo // miFrame.add(), sino que es una forma especial de invocar // al metodo necesaria para poder asociar un objeto Barra de Menu // a un objeto Frame Frame miFrame = new Frame( "Tutorial de Java, AWT" ); // Esto no es el metodo add(), como se podria esperar miFrame.setMenuBar( barraMenu ); miFrame.setSize( 250,100 ); miFrame.setVisible( true ); // Instancia y registra un receptor de eventos de ventana para // concluir la ejecucion del programa cuando se cierra el Frame miFrame.addWindowListener( new Conclusion() ); } } // Clase para instanciar un objeto ItemListener y registrarlo // sobre los elementos del menu class ControladorCheckBox implements ItemListener { public void itemStateChanged( ItemEvent evt ) { // Presenta en pantalla el elemento del menu que ha // generado el evento System.out.println( evt.getSource() ); } } class Conclusion extends WindowAdapter { public void windowClosing( WindowEvent evt ) { // Termina el programa cuando se cierra la ventana System.exit( 0 ); } } Hay algunos trozos de código en el programa que resultan repetitivos, debido al hecho de que se utiliza básicamente el mismo código para crear cada elemento del menú y registrar un objeto Listener sobre él. El orden en que se instancian y asocian las opciones es importante. La primera sentencia de código interesante es la que se utiliza para instanciar varios objetos CheckboxMenuItem que serán añadidos al objeto Menu para producir un menú con varias opciones. CheckboxMenuItem primerElementoMenu = new CheckboxMenuItem( "Primer Elemento" ); La sentencia que se reproduce ahora es interesante solamente por lo que tiene de novedad, porque hace uso de un tipo de clase Listener que no se ha visto antes. La sentencia, por otro lado, es la típica que se requiere para instanciar y registrar objetos ItemListener sobre cada CheckboxMenuItem. primerElementoMenu.addItemListener( new ControladorCheckBox() ); A continuación se encuentra el código que instancia un objeto Menu y le añade los objetos CheckboxMenuItem, que es semejante al utilizado en los menús normales. El siguiente código interesante corresponde a la clase que implementa el interfaz ItemListener, que vuelve a resultar interesante por lo novedoso. Kena Puga Nathal Página 7 09/08/2017 7 class ControladorCheckBox implements ItemListener { public void itemStateChanged( ItemEvent evt ) { // Presenta en pantalla el elemento del menu que ha // generado el evento System.out.println( evt.getSource() ); } } Y el resto del programa es similar al de ejemplos anteriores, así que no se vuelve más sobre él. Clase PopupMenu Esta clase se utiliza para instanciar objetos que funcionan como menús emergentes o pop-up. Una vez que el menú aparece en pantalla, el procesado de las opciones es el mismo que en el caso de los menús de persiana. Esta clase proporciona un par de constructores y un par de métodos, de los cuales el más interesante es el método show(), que permite mostrar el menú emergente en una posición relativa al Componente origen. Este Componente origen debe estar contenido dentro de la jerarquía de padres de la clase PopupMenu. Constructores: new PopupMenu(); new PopupMenu(“etiqueta”); Métodos: show(contenedor, x, y); //muestra el menú pero para ello debe conocer el contenedor donde se va a //mostrar y las posiciones sobre las cuales se visualizará Para el manejo de este tipo de menús, en necesario también manejar eventos del ratón de manera que se puedan obtener las coordenadas sobre las cuales se presentará el menú. El programa siguiente, java1319.java, coloca un objeto PopupMenu sobre un objeto Frame. El menú contiene tres opciones de tipo CheckboxMenuItem, y aparece cuando se pica dentro del Frame, posicionando su esquina superior-izquierda en la posición en que se encontraba el ratón en el momento de pulsar el botón. El resto del funcionamiento es semejante al de los programas de ejemplo vistos en secciones anteriores import java.awt.*; import java.awt.event.*; public class java1319 { public static void main( String args[] ) { IHM ihm = new IHM(); } } class IHM { public IHM() { // Instancia objetos CheckboxMenuItem CheckboxMenuItem primerElementoMenu = new CheckboxMenuItem( "Primer Elemento" ); CheckboxMenuItem segundoElementoMenu = new CheckboxMenuItem( "Segundo Elemento" ); CheckboxMenuItem tercerElementoMenu = new CheckboxMenuItem( "Tercer Elemento" ); // Se instancia un objeto ItemListener y se registra sobre los Kena Puga Nathal Página 8 09/08/2017 8 // elementos de menu ya instanciados primerElementoMenu.addItemListener( new ControladorCheckBox() ); segundoElementoMenu.addItemListener( new ControladorCheckBox() ); tercerElementoMenu.addItemListener( new ControladorCheckBox() ); // Instancia un objeto Menu de tipo PopUp y le añade los objetos // CheckboxMenuItem PopupMenu miMenuPopup = new PopupMenu( "Menu Popup" ); miMenuPopup.add( primerElementoMenu ); miMenuPopup.add( segundoElementoMenu ); miMenuPopup.add( tercerElementoMenu ); Frame miFrame = new Frame( "Tutorial de Java, AWT" ); miFrame.addMouseListener( new ControladorRaton(miFrame,miMenuPopup) ); // Aquí está la diferencia con los Menus de Barra miFrame.add( miMenuPopup ); miFrame.setSize( 250,100 ); miFrame.setVisible( true ); // Instancia y registra un receptor de eventos de ventana para // terminar el programa cuando se cierra el Frame miFrame.addWindowListener( new Conclusion() ); } } // Clase para atrapar los eventos de pulsacion del raton y presentar // en la pantalla el objeto menu Popup, en la posicion en que se // encontraba el cursor class ControladorRaton extends MouseAdapter{ Frame aFrame; PopupMenu aMenuPopup; // Constructor parametrizado ControladorRaton( Frame frame,PopupMenu menuPopup ) { aFrame = frame; aMenuPopup = menuPopup; } public void mousePressed( MouseEvent evt ) { // Presenta el menu PopUp sobre el Frame que se especifique // y en las coordenadas determinadas por el click del raton, // cuidando de que las coordenadas no se encuentren situadas // sobre la barra de titulo, porque las coordenadas Y en // esta zona son negativas if( evt.getY() > 0 ) aMenuPopup.show( aFrame,evt.getX(),evt.getY() ); } } // Clase para instanciar un objeto receptor de eventos de los // elementos del menu que sera registrado sobre estos elementos class ControladorCheckBox implements ItemListener { public void itemStateChanged( ItemEvent evt ) { // Presenta en pantalla el elemento que ha generado el // evento System.out.println( evt.getSource() ); } } class Conclusion extends WindowAdapter { public void windowClosing( WindowEvent evt ) { // termina el programa cuando se cierra la ventana System.exit( 0 ); } Kena Puga Nathal Página 9 09/08/2017 9 } El programa es muy similar al de la sección anterior en que se utilizaban objetos CheckboxMenuItem en un menú de persiana normal, así que solamente se verá el código que afecta al uso del objeto PopupMenu. El primer fragmento de código interesante es el que instancia un objeto PopupMenu y le incorpora tres objetos CheckboxMenuItem. PopupMenu miMenuPopup = new PopupMenu( "Menu Popup" ); miMenuPopup.add( primerElementoMenu ); miMenuPopup.add( segundoElementoMenu ); miMenuPopup.add( tercerElementoMenu ); El siguiente trozo de código es interesante porque el procedimiento en el caso de asociar un objeto PopupMenu con el objeto Frame, es diferente a cuando se utiliza un objeto MenuBar. En el caso de la barra de menú, se utiliza la llamada al método setMenuBar(), mientras que para asociar un menú emergente a un objeto Frame, se utiliza la típica llamada de la forma Objeto.add(), que es el método habitual de añadir muchos otros Componentes a un Contenedor. Frame miFrame = new Frame( "Tutorial de Java, AWT" ); miFrame.addMouseListener( new ControladorRaton(miFrame,miMenuPopup) ); // Aquí está la diferencia con los Menus de Barra miFrame.add( miMenuPopup ); El siguiente trozo de código interesante es el método sobrescrito mousePressed(), del interfaz MouseListener, encapsulado aquí en la clase ControladorRaton. El propósito de esta clase es instanciar un objeto receptor que atrapará eventos de pulsación del ratón sobre el objeto Frame, y mostrará el objeto PopupMenu en la posición en que se encuentre el cursor del ratón en el momento de producirse el evento. public void mousePressed( MouseEvent evt ) { // Presenta el menu PopUp sobre el Frame que se especifique // y en las coordenadas determinadas por el click del raton, // cuidando de que las coordenadas no se encuentren situadas // sobre la barra de titulo, porque las coordenadas Y en // esta zona son negativas if( evt.getY() > 0 ) aMenuPopup.show( aFrame,evt.getX(),evt.getY() ); } Como se puede observar, es lo típico, excepto el uso del método show() de la clase PopupMenu. También se debe notar la referencia al objeto PopupMenu y otra al objeto Frame, que se pasan cuando se instancia el objeto. Estas dos referencias son necesarias para la invocación del método show(), tal como se muestra en el código anterior. La referencia al objeto Frame se utiliza para establecer la posición en donde aparecerá el menú, y la referencia al objeto PopupMenu especifica el menú que se debe mostrar. Otros ejemplos del manejo de menús: import java.awt.*; import java.awt.event.*; public class ejem_menu extends Frame {//creo barra de menus MenuBar barra=new MenuBar(); //creo menus Menu subm1=new Menu("menu1"); Menu subm2=new Menu("menu2"); Menu subm3=new Menu("menu3"); Menu subm4=new Menu ("submenu"); //creo opciones del menu MenuItem op1=new MenuItem("op1"); Kena Puga Nathal Página 10 09/08/2017 10 MenuItem op2=new MenuItem("op2"); MenuItem op3=new MenuItem("op3"); MenuItem op4=new MenuItem("op4"); MenuItem op5=new MenuItem("op5"); MenuItem op6=new MenuItem("op6"); MenuItem op7=new MenuItem("op7"); MenuItem op8=new MenuItem("op8"); MenuItem op9=new MenuItem("op9"); MenuItem op10=new MenuItem("op10"); MenuItem op11=new MenuItem("op11"); CheckboxMenuItem op12 = new CheckboxMenuItem("casilla de seleccion"); public ejem_menu() {//agrego las opciones a cada menú, construyo cada menu subm1.add(op1); subm1.add(op2); subm2.add(op3); subm2.add(op4); subm2.addSeparator(); // se agrega una linea de separacion en el menu 2 subm2.add(op5); subm2.add(op6); subm2.add(op7); subm3.add(op8); subm3.add(op9); subm3.addSeparator();// se agrega una linea de separacion en el menu 3 subm4.add(op10); subm4.add(op11); subm4.addSeparator();// se agrega una linea de separacion en el menu 4 subm4.add(op12); subm4.addSeparator();// se agrega una linea de separacion en el menu 4 subm3.add(subm4); //construyo la barra de menús barra.add(subm1); barra.add(subm2); barra.add(subm3); //agrego la barra de menús al frame setMenuBar(barra); this.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}}); } public static void main(String arg[]) {ejem_menu em=new ejem_menu(); em.setSize(400,400); em.setVisible(true); } } *+*+*+*+* import java.awt.*; import java.awt.event.*; import java.applet.*; public class emergente extends Applet implements ActionListener, MouseListener {Label label; PopupMenu pop=new PopupMenu("Menu emergente"); MenuItem op1=new MenuItem("opcion1"); MenuItem op2=new MenuItem("opcion2"); MenuItem op3=new MenuItem("opcion3"); MenuItem op4=new MenuItem("opcion4"); public void init() {op1.addActionListener(this); Kena Puga Nathal Página 11 09/08/2017 11 op2.addActionListener(this); op3.addActionListener(this); op4.addActionListener(this); pop.add(op1); pop.addSeparator(); pop.add(op2); pop.addSeparator(); pop.add(op3); pop.addSeparator(); pop.add(op4); pop.addSeparator(); add(pop); label=new Label("hola hola!!!!"); add(label); /* addMouseListener(new MouseAdapter() {public void mousePressed(MouseEvent e) {if (e.getModifiers()!=0) {pop.show(this,e.getX(),e.getY());} } }); */ addMouseListener(this); /* addWindowListener(new WindowAdapter () {public void windowClosing(WindowEvent e) { setVisible(false); System.exit(0); } }); */ } public void mousePressed(MouseEvent e) {if (e.getModifiers()!=0) {pop.show(this,e.getX(),e.getY());} } public void mouseClicked(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void actionPerformed(ActionEvent e) {if (e.getSource()==op1) label.setText("eligio opcion 1"); else if (e.getSource()==op2) label.setText("se eligio opcion2"); else if (e.getSource()==op3) label.setText("se eligio opcion3"); else if (e.getSource()==op4) label.setText("se eligio opcion4"); } /* public static void main(String arg []) {emergente emer=new emergente(); emer.setSize(300,300); emer.setVisible(true); } */ } /* <html> <applet code="emergente.class" width=500 height=400> </applet> </html> */ *+*+*+*+* import java.awt.*; import java.awt.event.*; import java.io.IOException; public class ejemMenu1 extends Frame implements ActionListener, ItemListener {Color c; CheckboxMenuItem esm_1=new CheckboxMenuItem("rojo"); CheckboxMenuItem esm_2=new CheckboxMenuItem("verde"); CheckboxMenuItem esm_3=new CheckboxMenuItem("azul"); Kena Puga Nathal Página 12 09/08/2017 12 MenuItem em2_1=new MenuItem("opcion 21"); MenuItem em2_2=new MenuItem("opcion 22"); public ejemMenu1() {setLayout(new FlowLayout()); MenuBar mb=new MenuBar(); Menu m1=new Menu("Menu 1"); Menu m2=new Menu("Menu 2"); Menu sm=new Menu("Submenu"); MenuItem em1_1=new MenuItem("opcion 1"); MenuItem em1_2=new MenuItem("opcion 2"); MenuItem em1_3=new MenuItem("opcion 3",new MenuShortcut(KeyEvent.VK_O, false)); em1_1.addActionListener(this); em1_2.addActionListener(this); em1_3.addActionListener(this); em2_1.addActionListener(this); em2_2.addActionListener(this); esm_1.addItemListener(this); esm_2.addItemListener(this); esm_3.addItemListener(this); setMenuBar(mb); mb.add(m1); mb.add(m2); m1.add(em1_1); m1.add(em1_2); m1.add(em1_3); m1.addSeparator(); m1.add(sm); sm.add(esm_1); sm.add(esm_2); sm.add(esm_3); m2.add(em2_1); m2.add(em2_2); em2_1.setEnabled(false); } public void actionPerformed(ActionEvent e) {if ((String)e.getActionCommand()=="opcion 1") {try{(Runtime.getRuntime()).exec("notepad.exe");} catch(IOException ee){} }else if ((String)e.getActionCommand()=="opcion 2") {try{(Runtime.getRuntime()).exec("java ejemMenu1");} catch(IOException ee){} }else if ((String)e.getActionCommand()=="opcion 3") {System.exit(0);}else if ((String)e.getActionCommand()=="opcion 21") {em2_1.setEnabled(false); em2_2.setEnabled(true); }else if ((String)e.getActionCommand()=="opcion 22") {em2_2.setEnabled(false); em2_1.setEnabled(true); } } public void itemStateChanged(ItemEvent e) {if(e.getSource()==esm_1) {if (esm_1.getState()) {c=new Color((int)(Math.random()*256),0,0); esm_2.setState(false); Kena Puga Nathal Página 13 09/08/2017 13 esm_3.setState(false); }} else if(e.getSource()==esm_2) {if(esm_2.getState()) {c=new Color(0,(int)(Math.random()*256),0); esm_1.setState(false); esm_3.setState(false); }} else if(e.getSource()==esm_3) {if(esm_3.getState()) {c=new Color(0,0,(int)(Math.random()*256)); esm_1.setState(false); esm_2.setState(false); }} repaint(); } public void paint(Graphics g) {g.setColor(c); g.fillOval(20,200,50,50); } public static void main(String arg[]) {ejemMenu1 eje=new ejemMenu1(); eje.setSize(500,500); eje.setVisible(true); eje.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}}); } } *+*+*+*+*+*+*+* import java.awt.*; import java.awt.event.*; import java.io.IOException; public class ejemMenu2 extends Frame implements ActionListener//, MouseListener { PopupMenu m1=new PopupMenu("Menu 1"); public ejemMenu2() {setLayout(new FlowLayout()); Menu sm=new Menu("Submenu"); MenuItem em1_1=new MenuItem("opcion 1"); MenuItem em1_2=new MenuItem("opcion 2"); MenuItem em1_3=new MenuItem("opcion 3",new MenuShortcut(KeyEvent.VK_O, false)); em1_1.addActionListener(this); em1_2.addActionListener(this); em1_3.addActionListener(this); m1.add(em1_1); m1.add(em1_2); m1.addSeparator(); sm.add(em1_3); m1.add(sm); add(m1); setFont(new Font("",0,24)); add((new Label("ejemplo de un menu emergente"))); // addMouseListener(this); addMouseListener(new Posicion(this,m1)); } public void actionPerformed(ActionEvent e) {if ((String)e.getActionCommand()=="opcion 1") {try{(Runtime.getRuntime()).exec("notepad.exe");} catch(IOException ee){} Kena Puga Nathal Página 14 09/08/2017 14 }else if ((String)e.getActionCommand()=="opcion 2") {try{(Runtime.getRuntime()).exec("java ejemMenu1");} catch(IOException ee){} }else if ((String)e.getActionCommand()=="opcion 3") {System.exit(0);}//else } /* public void mousePressed(MouseEvent e) {m1.show(this,e.getX(),e.getY());} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} */ public static void main(String arg[]) {ejemMenu2 eje=new ejemMenu2(); eje.setSize(500,500); eje.setVisible(true); eje.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}}); } class Posicion extends MouseAdapter {private Frame f; private PopupMenu pm; public Posicion(Frame f, PopupMenu pm) {this.f=f; this.pm=pm; } public void mousePressed(MouseEvent e) {pm.show(f,e.getX(),e.getY());} } } *+*+*+*+*+*+*+*+* import java.awt.*; import java.awt.event.*; import java.io.IOException; public class ejemMenu3 extends Frame implements ActionListener, MouseListener {PopupMenu m1=new PopupMenu("Menu 1"); public ejemMenu3() {setLayout(new FlowLayout()); Menu sm=new Menu("Submenu"); MenuItem em1_1=new MenuItem("opcion 1"); MenuItem em1_2=new MenuItem("opcion 2"); MenuItem em1_3=new MenuItem("opcion 3",new MenuShortcut(KeyEvent.VK_O, false)); em1_1.addActionListener(this); em1_2.addActionListener(this); em1_3.addActionListener(this); m1.add(em1_1); m1.add(em1_2); m1.addSeparator(); sm.add(em1_3); m1.add(sm); add(m1); setFont(new Font("",0,24)); Kena Puga Nathal Página 15 09/08/2017 15 add((new Label("ejemplo de un menu emergente"))); addMouseListener(this); // addMouseListener(new Posicion(this,m1)); } public void actionPerformed(ActionEvent e) {if ((String)e.getActionCommand()=="opcion 1") {try{(Runtime.getRuntime()).exec("notepad.exe");} catch(IOException ee){} }else if ((String)e.getActionCommand()=="opcion 2") {try{(Runtime.getRuntime()).exec("java ejemMenu1");} catch(IOException ee){} }else if ((String)e.getActionCommand()=="opcion 3") {System.exit(0);} } public void mousePressed(MouseEvent e) {m1.show(this,e.getX(),e.getY());} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public static void main(String arg[]) {ejemMenu2 eje=new ejemMenu2(); eje.setSize(500,500); eje.setVisible(true); eje.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}}); } /* class Posicion extends MouseAdapter {private Frame f; private PopupMenu pm; public Posicion(Frame f, PopupMenu pm) {this.f=f; this.pm=pm; } public void mousePressed(MouseEvent e) {pm.show(f,e.getX(),e.getY());} } */ } *+*+*+*+*+*+*+*+* import java.awt.*; import java.awt.event.*; import java.io.IOException; public class ejemMenu5 extends Frame implements ActionListener {PopupMenu m1=new PopupMenu("Menu 1"); PopupMenu sm=new PopupMenu("Menu 2"); MenuItem em1_1=new MenuItem("Bloc de notas"); MenuItem em1_2=new MenuItem("Menu 1"); MenuItem em1_3=new MenuItem("Salir",new MenuShortcut(KeyEvent.VK_S, false)); public ejemMenu5() {setLayout(new FlowLayout()); em1_1.addActionListener(this); em1_2.addActionListener(this); Kena Puga Nathal Página 16 09/08/2017 16 em1_3.addActionListener(this); m1.add(em1_1); m1.addSeparator(); m1.add(em1_2); sm.add(em1_3); add(sm); add(m1); setFont(new Font("",0,24)); add((new Label("ejemplo de un menu emergente"))); addMouseListener(new Posicion(this,m1)); addMouseListener(new Posicion(this,sm)); } public void actionPerformed(ActionEvent e) {if (e.getSource()==em1_1) {try{(Runtime.getRuntime()).exec("notepad.exe");} catch(IOException ee){} }else if (e.getSource()==em1_2) {try{(Runtime.getRuntime()).exec("java ejemMenu1");} catch(IOException ee){} }else if (e.getSource()==em1_3) {System.exit(0);} } public static void main(String arg[]) {ejemMenu5 eje=new ejemMenu5(); eje.setSize(500,500); eje.setVisible(true); eje.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}}); } class Posicion extends MouseAdapter {private Frame f; private PopupMenu pm; public Posicion(Frame f, PopupMenu pm) {this.f=f; this.pm=pm; } public void mousePressed(MouseEvent e) {//System.out.println(e.getButton()); if(((pm.getLabel().equals("Menu 1"))&&(e.getButton()==MouseEvent.BUTTON1))||((pm.getLabel().equals("Menu 2"))&&(e.getButton()==MouseEvent.BUTTON3))) {pm.show(f,e.getX(),e.getY());} } } } *+*+*+*+*+*+*+*+*+*+*+* import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; public class ejemMenu4 extends Frame implements ActionListener, ItemListener {Color c; Button b1; Button b2; Button b3; CheckboxMenuItem esm_1=new CheckboxMenuItem("rojo"); CheckboxMenuItem esm_2=new CheckboxMenuItem("verde"); CheckboxMenuItem esm_3=new CheckboxMenuItem("azul"); Kena Puga Nathal Página 17 09/08/2017 17 PopupMenu emergente=new PopupMenu("Menu emergente"); MenuItem em2_1=new MenuItem("opcion 21"); MenuItem em2_2=new MenuItem("opcion 22"); public ejemMenu4() {setLayout(new FlowLayout()); MenuBar mb=new MenuBar(); Menu m1=new Menu("Menu 1"); Menu m2=new Menu("Menu 2"); Menu sm=new Menu("Submenu"); MenuItem em1_1=new MenuItem("opcion 1"); MenuItem em1_2=new MenuItem("opcion 2"); MenuItem em1_3=new MenuItem("opcion 3",new MenuShortcut(KeyEvent.VK_O, false)); b1=new Button("Opcion 1"); b2=new Button("Opcion 2"); b3=new Button("Opcion 3"); em1_1.addActionListener(this); em1_2.addActionListener(this); em1_3.addActionListener(this); em2_1.addActionListener(this); em2_2.addActionListener(this); esm_1.addItemListener(this); esm_2.addItemListener(this); esm_3.addItemListener(this); b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); setMenuBar(mb); mb.add(m1); mb.add(m2); m1.add(em1_1); m1.add(em1_2); m1.add(em1_3); m1.addSeparator(); m1.add(sm); sm.add(esm_1); sm.add(esm_2); sm.add(esm_3); m2.add(em2_1); m2.add(em2_2); em2_1.setEnabled(false); emergente.add(m1); emergente.addSeparator(); emergente.add(em2_1); emergente.add(em2_2); add(emergente); addMouseListener(new Posicion(this, emergente)); add(b1); add(b2); add(b3); } public void actionPerformed(ActionEvent e) {if ((String)e.getActionCommand()=="opcion 1" || e.getSource()==b1) {try{(Runtime.getRuntime()).exec("C:\\Archivos de programa\\Internet Explorer\\Iexplore.exe "+new URL("file:"+(new File("CGraficos.html")).getAbsolutePath()));} catch(IOException ee){} }else if ((String)e.getActionCommand()=="opcion 2" || e.getSource()==b2) {try{(Runtime.getRuntime()).exec("animacion1");} catch(IOException ee){} }else Kena Puga Nathal Página 18 09/08/2017 18 if ((String)e.getActionCommand()=="opcion 3" || e.getSource()==b3) {System.exit(0);}else if ((String)e.getActionCommand()=="opcion 21") {em2_1.setEnabled(false); em2_2.setEnabled(true); }else if ((String)e.getActionCommand()=="opcion 22") {em2_2.setEnabled(false); em2_1.setEnabled(true); } } public void itemStateChanged(ItemEvent e) {if(e.getSource()==esm_1) {if (esm_1.getState()) {c=new Color((int)(Math.random()*256),0,0); esm_2.setState(false); esm_3.setState(false); }} else if(e.getSource()==esm_2) {if(esm_2.getState()) {c=new Color(0,(int)(Math.random()*256),0); esm_1.setState(false); esm_3.setState(false); }} else if(e.getSource()==esm_3) {if(esm_3.getState()) {c=new Color(0,0,(int)(Math.random()*256)); esm_1.setState(false); esm_2.setState(false); }} repaint(); } public void paint(Graphics g) {g.setColor(c); g.fillOval(20,200,50,50); } public static void main(String arg[]) {ejemMenu4 eje=new ejemMenu4(); eje.setSize(500,500); eje.setVisible(true); eje.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}}); } } class Posicion extends MouseAdapter {private Frame f; private PopupMenu pm; public Posicion(Frame f, PopupMenu pm) {this.f=f; this.pm=pm; } public void mousePressed(MouseEvent e) {pm.show(f,e.getX(),e.getY());} } Informacion tomada del tutorial de la pagina: http://dis.um.es/~bmoros/Tutorial/parte13/cap13-6.html Kena Puga Nathal Página 19 09/08/2017 19