Topicos GUI Avanzados - Cómputo

Un contenedor de nivel superior puede tener una barra de menú. ...... main() al final de la clase crea una instancia de
284KB Größe 2 Downloads 138 Ansichten
Topicos GUI Avanzados H. Tejeda Mayo 2016

´Indice 1. Panel de contenido

1

2. Clase Color

4

3. Manejadores de dise˜ no

5

4. JPanel

12

5. JScrollPane

16

6. Eventos y su manejo

18

7. M´ etodos de la clase AWTEvent

23

8. Manejo de eventos del rat´ on

23

9. Uso de men´ us

28

1.

Panel de contenido

La clase JFrame es una clase Java Swing contenedora de nivel superior. Las otras dos clases contenedoras de nivel superior son JDialog y JApplet. Cada componente GUI (Graphical User Interface) que aparece en la pantalla deber´a ser parte de una jerarqu´ıa de contenci´on. Una jerarqu´ıa de contenci´ on es un ´ arbol de componentes que tienen un contenedor de nivel superior como su ra´ız. Cada contenedor de nivel superior tiene un panel de contenido que contiene todos los componentes visibles en la interfaz de usuario del contenedor. El panel de contenido puede contener directamente componentes como JButton, u otros contenedores, como JPanel, que a su vez puede contener componentes. 1

Un contenedor de nivel superior puede tener una barra de men´ u. Una barra de men´ u es una tira horizontal que convencionalmente est´ a puesta en la cima de un contenedor y tiene opciones para el usuario. La barra de men´ u est´ a encima del panel de contenido. Un panel de cristal est´a encima del panel de contenido. En la siguiente figura se muestra la relaci´on entre un JFrame y su p´aneles ra´ız, de contenido y de cristal. +---------------------+ | JFrame | | +--------------------+ | | Panel ra´ ız | | | +--------------------+ | | | Barra de men´ u | | | |--------------------| +---| | Panel de contenido | | | +-------------------+ +---| | Panel de cristal | | | | +---| | | | | | | | +-------------------+ Nota. En el panel de cristal residen los tool tips. Se pueden dibujar sus propios gr´aficos en este panel “en la cima de” los componentes en un JFrame o JApplet. Si se agrega un MouseListener al panel de cristal, este previene que el rat´on dispare eventos en los componentes debajo del panel de cristal en el JFrame. Existe un panel adicional encima del panel ra´ız, pero este no es usado frecuentemente por los programadores.

Para obtener una referencia al panel de contenido de un JFrame, u otro contenedor de nivel superior, se usa el m´etodo getContentPane(). Los m´etodos add() y remove() usados para agregar y quitar componentes de objetos JFrame y el m´etodo setLayoutManager() usado para poner el manejador de dise˜ no tienen esas habilidades porque Java los convierte en versiones m´as completas. Por ejemplo, las siguientes tres sentencias son equivalentes dentro de una clase que descienda de JFrame: this.getContentPane().add(unBoton); getContentPane().add(unBoton); add(unBoton); En la primera sentencia, this se refiere a la clase JFrame en el cual la sentencia aparece, y getContentPane() da una referencia al panel de contenido. En la segunda sentencia, la referencia this est´ a implicada. En la tercera sentencia, la referencia this y la llamada al m´etodo getContentPane() est´ an implicados.

2

No se requiere preocuparse por el panel de contenido si s´olo se agregan componentes, se quitan o se pone el manejador de dise˜ no de un JFrame, pero se deber´a referir al panel de contenido para todas las otras acciones, tales como poner el color del fondo. Cuando se escribe una aplicaci´ on en la cual se tenga que estar usando el panel de contenido, es m´as eficiente declarar un objeto que represente el panel de contenido que estar llamando al m´etodo getContentPane(), como se muestra en el siguiente ejemplo, donde la llamada al m´etodo getContentPane() es hecha una vez, su referencia se guarda en una variable, y luego el nombre de referencia es usada con la llamada al m´etodo add(): Container con = getContentPane(); con.add(boton1); con.add(boton2); con.add(boton3); En la clase JFrameConContentPane, c´ odigo 1, se crea un JFrame donde la operaci´on de cierre por defecto no fue puesta y al bot´ on no se le asign´o alguna funcionalidad, para que el ejemplo sea sencillo. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

import j a v a . awt . ∗ ; import j a v a x . swing . ∗ ; public c l a s s JFrameConContentPane extends JFrame { private f i n a l int TAM = 1 8 0 ; private C o n t a i n e r con = getContentPane ( ) ; private JButton boton = new JButton ( ” Pulsa aqu´ı” ) ; public JFrameConContentPane ( ) { super ( ” Ventana ” ) ; s e t S i z e (TAM, TAM) ; con . s e t L a y o u t (new FlowLayout ( ) ) ; con . add ( boton ) ; } public s t a t i c void main ( S t r i n g [ ] a r g s ) { JFrameConContentPane marco = new JFrameConContentPane ( ) ; marco . s e t V i s i b l e ( true ) ; } }

C´ odigo 1: La clase JFrameConContentPane. En el c´odigo 1 en la l´ınea 5 la llamada del m´etodo getContentPane() se asigna una referencia a un Container llamado con, y luego es usada con los m´etodos setLayout() y add() en las l´ıneas 10 y 11 respectivamente. Cuando se quieren usar otros m´etodos en vez de add(), remove(), o setLayout() con un JFrame, se debe usar un panel de contenido, como cuando se emplea el m´etodo setBackground() usado para cambiar el color del fondo. Si este m´etodo se usa con un JFrame el usuario no ver´a los resultados.

3

2.

Clase Color

La clase Color define colores para ser usados en aplicaciones, por ejemplo con los m´etodos setBackground() y setForeground() de la clase Component. Cuando se usa la clase Color, se debe incluir la sentencia import java.awt.Color; al inicio del archivo de la clase. La clase Color define constantes con nombre que representan trece colores, como se muestra en el cuadro 1. Las constantes en Java son escritas usualmente con todas las letras en may´ usculas. Sin embargo, los creadores de Java declararon dos constantes para cada color en la clase Color—una versi´on con may´ usculas, y la otra con min´ usculas. Las primeras versiones de Java conten´ıan s´ olo las constantes con min´ usculas. Constante min´ usculas BLACK BLUE CYAN DARK GRAY GRAY GREEN LIGHT GRAY MAGENTA ORANGE PINK RED WHITE YELLOW

Constante may´ usculas black blue cyan darkgray gray green lightgray magenta orange pink red white yellow

Color negro azul cian gris obscuro gris verde gris claro magenta naranja rosa rojo blanco amarillo

Cuadro 1: Constantes de la clase Color. Para crear un objeto Color propio se har´ıa de la siguiente forma: Color algunColor = new Color(r, g, b); En la sentencia previa, r, g, y b son n´ umeros que representan las intensidades de rojo, verde, y azul que se quieren en el color. El rango de los n´ umeros est´a entre 0 y 255. Para crear el color negro se requiere que los valores de r, g, y b sean cero, y para el color blanco es con 255. En la siguiente sentencia se genera el color p´ urpura obscuro que tiene componentes para el rojo y el azul, pero carece de verde. Color purpuraObscuro = new Color(100, 0, 100); Se pueden crear m´ as de 16 millones, 224 , de colores personalizados de la forma anterior. Algunos computadoras no pueden mostrar cada uno de los 16 millones de colores posibles; cada computadora muestra el color m´ as cercano que puede al color solicitado.

4

Para determinar la cantidad de los componentes rojo, verde, o azul de alg´ un objeto Color se usan los m´etodos getRed(), getGreen(), o getBlue() respectivamente. Cada uno de los m´etodos devuelve un entero. Por ejemplo, para saber la cantidad de rojo en MAGENTA se usa Color.MAGENTA.getRed(). La aplicaci´on JFrameConColor, c´ odigo 2, pone el color del fondo de un panel de contenido JFrame y los colores del frente y el fondo de un JButton. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

import j a v a . awt . ∗ ; import j a v a x . swing . ∗ ; public c l a s s JFrameConColor extends JFrame { private f i n a l int TAM = 1 8 0 ; private C o n t a i n e r con = getContentPane ( ) ; private JButton boton = new JButton ( ” Pulsa aqu´ı” ) ; public JFrameConColor ( ) { super ( ”Marco” ) ; s e t S i z e (TAM, TAM) ; con . s e t L a y o u t (new FlowLayout ( ) ) ; con . add ( boton ) ; con . setBackground ( C o l o r .YELLOW) ; boton . setBackground ( C o l o r .RED) ; boton . s e t F o r e g r o u n d ( C o l o r .BLUE ) ; } public s t a t i c void main ( S t r i n g [ ] a r g s ) { JFrameConColor marco = new JFrameConColor ( ) ; marco . s e t V i s i b l e ( true ) ; } }

C´ odigo 2: La aplicaci´on JFrameConColor.

3.

Manejadores de dise˜ no

Un manejador de dise˜ no es un objeto que controla el tama˜ no y la posici´on (que es, el dise˜ no) de componentes dentro de un objeto Container. Dependiendo del manejador de dise˜ no que se asigne a un Container este determina como sus componentes son dimensionados y posicionados. Los manejadores de dise˜ no son clases interfaz que son parte del JDK; estos alinean los componentes para que ni se amontonen, ni se traslapen. Por ejemplo, el manejador de dise˜ no FlowLayout coloca los componentes en renglones de izquierda a derecha a trav´es de su contenedor. Otros manejadores de dise˜ no ponen los componentes en columnas y renglones de tama˜ no igual o centran los componentes dentro de su contenedor. Cada componente que se pone dentro de un Container puede tambi´en ser un Container por s´ı mismo, as´ı que se pueden asignar manejadores de dise˜ no dentro de otros. Java proporciona manejadores de dise˜ no que van desde los muy simples, como FlowLayout y GridLayout, los de prop´ osito especial, como BorderLayout y CardLayout, a los muy flexibles, como GridBagLayout y BoxLayout. En el cuadro 2 se listan cada uno de los manejadores de dise˜ no y las situaciones en las cuales son com´ unmente empleados.

5

Manejador BorderLayout FlowLayout

GridLayout CardLayout GridBagLayout

Descripci´ on Usar para agregar hasta cinco componentes. Usar para agregar componentes de izquierda a derecha; cuando el rengl´on se llena se pasa autom´aticamente al siguiente rengl´on, y cada componente toma su tama˜ no preferente. Usar para agregar componentes en una malla de renglones y columnas; cada componente es del mismo tama˜ no. Usar para agregar componentes que sean mostrados uno a la vez. Usar cuando se necesite fijar tama˜ no, lugar, y restricciones de alineaci´on para cada componente que sea agregado. Cuadro 2: Manejadores de dise˜ no.

Clase BorderLayout El manejador BorderLayout es la clase manejadora por defecto para todos los p´aneles de contenido. Se puede usar la clase BorderLayout con cualquier contenedor que tenga 5 componentes o menos. Cualquiera de los componentes podr´ıa ser un contenedor que tenga m´as componentes. Con el manejador BorderLayout los componentes llenan la pantalla en cinco regiones: norte, sur, este, oeste y centro. Cuando se agrega un componente a un contenedor que usa BorderLayout, el m´etodo add() usa dos argumentos: el componente y la regi´on a la cual este es agregado. La clase BorderLayout proporciona cinco constantes con nombre para las regiones—BorderLayout.NORTH, .SOUTH, .EAST, .WEST, y .CENTER—o se pueden usar los String que estas constantes representan: “North”, “South”, “East”, “West”, o “Center”. La aplicaci´on DemoJBorderLayout, c´odigo 3, muestra una salida donde han sido puestos cinco botones. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

import j a v a . awt . ∗ ; import j a v a x . swing . ∗ ; public c l a s s DemoJBorderLayout extends JFrame { private JButton bn = new JButton ( ” Bot´on Norte ” ) ; private JButton bs = new JButton ( ” Bot´on Sur ” ) ; private JButton be = new JButton ( ” Bot´on Este ” ) ; private JButton bo = new JButton ( ” Bot´on Oeste ” ) ; private JButton bc = new JButton ( ” Bot´on Centro ” ) ; private C o n t a i n e r con = getContentPane ( ) ; public DemoJBorderLayout ( ) { con . s e t L a y o u t (new BorderLayout ( ) ) ; con . add ( bn , BorderLayout .NORTH) ; con . add ( bs , BorderLayout .SOUTH) ; con . add ( be , BorderLayout .EAST ) ; con . add ( bo , BorderLayout .WEST) ; con . add ( bc , ” Center ” ) ; s e t S i z e (400 , 150); } public s t a t i c void main ( S t r i n g [ ] a r g s ) { DemoJBorderLayout ventana =

6

21 22 23 24

new DemoJBorderLayout ( ) ; ventana . s e t V i s i b l e ( true ) ; } }

C´ odigo 3: Aplicaci´on DemoJBorderLayout. Nota. Cuando se usa BorderLayout, se pueden usar las constantes PAGE START, PAGE END, LINE START, LINE END, y CENTER en vez NORTH, SOUTH, EAST, WEST, y CENTER. Las constantes dadas corresponden a posiciones que se podr´ıan tener en una hoja impresa. Si se agrega la siguiente sentencia import, se puede referir a CENTER en vez de BorderLayout.CENTER: import static java.awt.BorderLayout.*;

Cuando se colocan cinco componentes en un contenedor y se usa BorderLayout, cada componente llena una regi´ on entera, como se observa al ejecutar la aplicaci´on DemoJBorderLayout. Cuando la aplicaci´on se ejecuta, Java determina el tama˜ no exacto de cada componente basado en el contenido del componente. Cuando se redimensiona un Container que use BorderLayout, las regiones tambi´en cambian en tama˜ no. Si el contenedor se hace m´as ancho las regiones norte, sur, y centro se hacen m´as anchas, pero las otras restantes no cambian. Si se incrementa la altura, las regiones este, oeste, y centro se hacen m´ as altas, pero las otras permanecen sin cambio. Cuando se usa BorderLayout, no se requiere agregar componentes en cada una de las cinco regiones. Si se agregan menos componentes, cualquier regi´on vac´ıa desaparece, y las restantes se expanden para llenar el espacio disponible. Si cualquiera de las regiones norte, sur, este, u oeste fueron dejadas vac´ıas, el ´area central se expande en las ´areas vac´ıas. Sin embargo, si el ´area central es dejada, ni la ´area norte, sur, este, u oeste cambia. Un error com´ un cuando se usa BorderLayout es agregar un componente a un panel de contenido o marco sin nombrar una regi´on. Esto puede resultar que algunos de los componentes no sea visible.

Clase FlowLayout Se puede usar el manejador FlowLayout para arreglar los componentes en renglones a lo ancho de un Container. Con un FlowLayout, cada componente que sea agregado es colocado a la derecha de los componentes previamente agregados en un rengl´on; o, si el rengl´on actual est´a lleno, el componente es puesto al inicio de un nuevo rengl´on. Cuando se usa BorderLayout, los componentes que se agregan llenan sus regiones. Sin embargo, cuando se usa FlowLayout, cada Component retiene su tama˜ no por defecto o tama˜ no preferente. Por ejemplo, el tama˜ no preferente de un JButton es el tama˜ no que es lo suficientemente grande para tener el texto del JButton. Cuando se usa un BorderLayout y luego se redimensiona la ventana, los componentes cambian su tama˜ no porque sus regiones cambian. Cuando se usa FlowLayout y luego se redimensiona la ventana, cada componente retiene su tama˜ no, pero este podr´ıa obscurecerse parcialmente o cambiar de posici´ on. La clase FlowLayout contiene tres constantes que se pueden usar para alinear Componentes en un Container: FlowLayout.LEFT 7

FlowLayout.CENTER FlowLayout.RIGHT Si no se indica la alineaci´ on, los componentes son alineados al centro en un Container con FlowLayout por defecto. En la aplicaci´on DemoJFlowLayout, c´odigo 4, un objeto FlowLayout llamado manejador es usado para poner el dise˜ no del panel de contenido. Cuando el usuario pulsa un bot´on, en las l´ıneas 19—22 el m´etodo actionPerformed() cambia la alineaci´on a la izquierda o a la derecha usando el m´etodo setAlignment(). Al ejecutar la DemoJFlowLayout se debe observar como los componentes JButton son reposicionados despu´es de que se pulsa en el bot´on izquierdo, y despu´es de hacerlo en el bot´ on derecho. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

import j a v a . awt . ∗ ; import j a v a . awt . e v e n t . ∗ ; import j a v a x . swing . ∗ ; public c l a s s DemoJFlowLayout extends JFrame implements A c t i o n L i s t e n e r { private JButton b i = new JButton ( ” Bot´on I z q u i e r d o ” ) ; private JButton bd = new JButton ( ” Bot´on Derecho ” ) ; private C o n t a i n e r con = getContentPane ( ) ; private FlowLayout manejador = new FlowLayout ( ) ; public DemoJFlowLayout ( ) { con . s e t L a y o u t ( manejador ) ; con . add ( b i ) ; con . add ( bd ) ; bi . addActionListener ( this ) ; bd . a d d A c t i o n L i s t e n e r ( t h i s ) ; s e t S i z e (500 , 100); } public void a c t i o n P e r f o r m e d ( ActionEvent e v e n t ) { Object s o u r c e = e v e n t . g e t S o u r c e ( ) ; i f ( s o u r c e == b i ) manejador . s e t A l i g n m e n t ( FlowLayout . LEFT ) ; else manejador . s e t A l i g n m e n t ( FlowLayout . RIGHT ) ; con . i n v a l i d a t e ( ) ; con . v a l i d a t e ( ) ; } public s t a t i c void main ( S t r i n g [ ] a r g s ) { DemoJFlowLayout ventana = new DemoJFlowLayout ( ) ; ventana . s e t V i s i b l e ( true ) ; } }

C´ odigo 4: Aplicaci´on DemoJFlowLayout.

Nota. Las sentencias de las l´ıneas 23 y 24 en el m´etodo actionPerformed() del c´odigo 4 llaman a los m´etodos invalidate() y validate(), respectivamente. La llamada invalidate() marca el contenedor, y cualquiera de sus padres, como necesitado de ser arreglado. La llamada validate() causa que los componentes sean redispuestos de acuerdo al manejador nuevo asignado.

8

Clase GridLayout Si quiere acomodar componentes en renglones y columnas del mismo tama˜ no, se puede usar la clase manejador GridLayout. Cuando se crea un objeto GridLayout se indica la cantidad de renglones y columnas deseadas, y entonces la superficie es dividida en una cuadr´ıcula. Con la siguiente sentencia se crea un GridLayout an´ onimo con cuatro renglones y cinco columnas en un Container llamado con: con.setLayout(new GridLayout(4, 5)); Cuando se agregan componentes a un GridLayout, estos son posicionados en secuencia de izquierda a derecha a trav´es de cada rengl´ on. No se puede saltar una posici´on o indicar una posici´on exacta para un componente. Sin embargo, se podr´ıa agregar una etiqueta blanca para simular el salto de una posici´on. Se puede tambi´en indicar una separaci´on vertical y horizontal medida en p´ıxeles, con dos argumentos adicionales. La aplicaci´on DemoJGridLayout, c´odigo 5, en la l´ınea 9 establece un GridLayout con tres renglones y dos columnas, e intervalos horizontal y vertical de cinco p´ıxeles cada uno. Cinco componentes JButton son agregadas al panel de contenido recuperado del JFrame. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

import j a v a . awt . ∗ ; import j a v a x . swing . ∗ ; public c l a s s DemoJGridLayout extends JFrame { private JButton b1 = new JButton ( ” Bot´on 1 ” ) ; private JButton b2 = new JButton ( ” Bot´on 2 ” ) ; private JButton b3 = new JButton ( ” Bot´on 3 ” ) ; private JButton b4 = new JButton ( ” Bot´on 4 ” ) ; private JButton b5 = new JButton ( ” Bot´on 5 ” ) ; private GridLayout d i s e n o = new GridLayout ( 3 , 2 , 5 , 2 ) ; private C o n t a i n e r con = getContentPane ( ) ; public DemoJGridLayout ( ) { con . s e t L a y o u t ( d i s e n o ) ; con . add ( b1 ) ; con . add ( b2 ) ; con . add ( b3 ) ; con . add ( b4 ) ; con . add ( b5 ) ; s e t S i z e (200 , 200); } public s t a t i c void main ( S t r i n g [ ] a r g s ) { DemoJGridLayout ventana = new DemoJGridLayout ( ) ; ventana . s e t V i s i b l e ( true ) ; } }

C´ odigo 5: Aplicaci´on DemoJGridLayout. Cuando se ejecuta la aplicaci´ on DemoJGridLayout, los componentes son puestos en el panel a trav´es de los tres renglones. Como hay seis posiciones pero s´olo cinco componentes, un lugar est´a sin usar. Con GridLayout, se puede indicar la cantidad de renglones y usar cero para la cantidad de columnas para permitir que el manejador de dise˜ no determine la cantidad de columnas, de igual forma se

9

puede indicar la cantidad de columnas y usar cero para la cantidad de renglones, para que el manejador calcula la cantidad de renglones. Cuando se intenta decidir entre usar un GridLayout o un FlowLayout, considerar lo siguiente: Usar GridLayout cuando se quiere a los componentes en renglones y columnas fijas, y se quiere que el tama˜ no de los componentes llene el espacio disponible. Usar FlowLayout si se quiere que Java determine los renglones y las columnas, en vez de algo fijo, para que los componentes retengan su tama˜ no “natural” para que sus contenidos sean completamente visibles.

Clase CardLayout El manejador CardLayout genera una pila de contenedores o componentes. Cada componente en el grupo es referido como una carta, y cada carta puede ser cualquier tipo de componente, como un JButton, un JLabel, o un JPanel. Se emplea un CardLayout cuando se quiere que componentes m´ ultiples compartan el mismo espacio de presentaci´on. Un manejador de cartas es creado de la clase CardLayout usando uno de dos constructores: CardLayout() crea un dise˜ no de cartas sin un intervalo horizontal o vertical. CardLayout(int hInt, int vInt) crea un dise˜ no de cartas con los intervalos horizontales y verticales especificados. Los intervalos horizontales son colocados en las aristas izquierda y derecha. Los intervalos verticales son colocados en las aristas de la cima y el fondo. La aplicaci´on DemoJCardLayout, c´ odigo 6, usa un manejador CardLayout para crear una pila de JButton que contienen las etiquetas “As de Corazones”, “Tres de Espadas”, “Reina de Tr´eboles”. En el constructor de la clase, se ocupa una versi´on ligeramente diferente del m´etodo add() para agregar componentes a un panel de contenido cuyo manejador de dise˜ no es CardLayout. El formato es: add(unString, unContenedor); En esta sentencia, unString representa el nombre que se quiere usar para identificar la carta componente que es agregada. 1 2 3 4 5 6 7 8 9 10

import j a v a . awt . ∗ ; import j a v a . awt . e v e n t . ∗ ; import j a v a x . swing . ∗ ; public c l a s s DemoJCardLayout extends JFrame implements A c t i o n L i s t e n e r { private CardLayout c a r t a s = new CardLayout ( ) ; private JButton b1 = new JButton ( ”As de Corazones ” ) ; private JButton b2 = new JButton ( ” Tres de Espadas ” ) ; private JButton b3 = new JButton ( ” Reina de Tr´e b o l e s ” ) ; private C o n t a i n e r con = getContentPane ( ) ; public DemoJCardLayout ( ) {

10

con . s e t L a y o u t ( c a r t a s ) ; con . add ( ” a s ” , b1 ) ; b1 . a d d A c t i o n L i s t e n e r ( t h i s ) ; con . add ( ” t r e s ” , b2 ) ; b2 . a d d A c t i o n L i s t e n e r ( t h i s ) ; con . add ( ” r e i n a ” , b3 ) ; b3 . a d d A c t i o n L i s t e n e r ( t h i s ) ; s e t S i z e (200 , 100);

11 12 13 14 15 16 17 18 19 20

} public void a c t i o n P e r f o r m e d ( ActionEvent e ) { c a r t a s . next ( getContentPane ( ) ) ; } public s t a t i c void main ( S t r i n g [ ] a r g s ) { DemoJCardLayout ventana = new DemoJCardLayout ( ) ; ventana . s e t V i s i b l e ( true ) ; }

21 22 23 24 25 26 27

}

C´ odigo 6: Aplicaci´on DemoJCardLayout. En un programa que tenga un manejador CardLayout, un cambio de carta es disparado por la acci´on del usuario. En el programa DemoJCardLayout, cada JButton dispara el m´etodo actionPerformed(). Dentro de este m´etodo, la sentencia next(getContentPane()) cambia a la siguiente carta del contenedor. El orden de las cartas depende del orden en cual fueron agregadas al contenedor. Se puede tambi´en usar previous(getContentPane());, first(getContentPane());, y last(getContentPane()); para cambiar a la carta previa, primera, y u ´ltima, respectivamente. Se puede ir a una carta espec´ıfica usando el nombre String asignado en la llamada al m´etodo add(). Para la aplicaci´ on del c´ odigo 6, la siguiente sentencia deber´a mostrar “Tres de Espadas” porque “tres” es usado como el primer argumento cuando el objeto b2 es agregado al panel de contenido en el constructor DemoJCardLayout: cards.show(getContentPane(), "tres"); Al ejecutar la aplicaci´ on DemoJCardLayout se muestra la primera carta, “As de Corazones”, y luego que el usuario pulsa una vez, aparece “Tres de Espadas”, y en la segunda pulsaci´on “Reina de Tr´eboles”. Como cada JButton es una carta, cada JButton usa el ´area de visualizaci´on completamente en el contenedor. Si el usuario contin´ ua pulsando los botones carta, las cartas se ciclan en orden.

Manejadores de dise˜ no avanzado El manejador GridBagLayout permite agregar componentes en lugares espec´ıficos en una cuadr´ıcula, al igual que se puede indicar que los componentes se expandan en m´ ultiples renglones y columnas. Por ejemplo, si se quiere crear un JPanel con seis JButton, en el cual dos de los JButton sean el doble de anchos que los otros, se puede usar GridBagLayout. Esta clase es dif´ıcil de usar porque se debe poner la posici´ on y el tama˜ no para cada componente, y m´as de veinte m´etodos est´an asociados con la clase.

11

Otra opci´on de manejador de dise˜ no es el manejador BoxLayout, el cual permite que varios componentes est´en puestos verticalmente u horizontalmente. Los componentes no se reacomodan cuando el marco es redimensionado, por ejemplo un arreglo vertical de componentes permanece vertical a pesar del redimensionado. Actividad 1. Crear un JFrame que use los diferentes manejadores de dise˜ no vistos en esta secci´ on.

4.

JPanel

Los manejadores BorderLayout, FlowLayout, GridLayout, y Cardlayout proporcionan una cantidad limitada de arreglos de pantalla si solo se pudiera colocar un solo Component en una secci´ on del dise˜ no. Pero, se puede incrementar la cantidad de arreglos de componentes posibles usando la clase JPanel. Un JPanel es un plano, superficie sin borde que puede tener componentes UI de peso ligero. Enseguida se muestra la jerarqu´ıa de herencia de la clase JPanel. java.lang.Object | +--java.awt.Component | +---java.awt.Container | +---javax.swing.JComponent | +---javax.swing.JPanel De la figura previa, se ve que cada JPanel es un Container; as´ı que se puede usar un JPanel para tener otros componentes UI, tales como JButton, JCheckBox, o incluso otros JPanel. Usando un JPanel dentro de otro, se puede crear una variedad infinita de dise˜ nos de pantalla. El manejador de dise˜ no por defecto para cada JPanel es FlowLayout. Para agregar un componente a un JPanel, se llama al m´etodo add() del contenedor, usando el componente como el argumento. La aplicaci´on JFrameConJPanels, c´odigo 7, extiende la clase JFrame. Un JButton es agregado a un JPanel llamado panel1, y dos JButton m´as son agregados a otro JPanel llamado panel2. Luego panel1 y panel2 son agregados a panel de contenido de un JFrame. 1 2 3 4 5 6 7 8 9 10 11 12

import j a v a . awt . ∗ ; import j a v a x . swing . ∗ ; import s t a t i c j a v a . awt . C o l o r . ∗ ; public c l a s s JFrameConJPanels extends JFrame { private f i n a l int ANCHO = 2 5 0 ; private f i n a l int ALTO = 1 2 0 ; private JButton boton1 = new JButton ( ”Uno” ) ; private JButton boton2 = new JButton ( ”Dos” ) ; private JButton boton3 = new JButton ( ” Tres ” ) ; public JFrameConJPanels ( ) { super ( ”JFrame con J P a n e l s ” ) ; s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;

12

JPanel p a n e l 1 = new JPanel ( ) ; JPanel p a n e l 2 = new JPanel ( ) ; C o n t a i n e r con = getContentPane ( ) ; con . s e t L a y o u t (new FlowLayout ( ) ) ; con . add ( p a n e l 1 ) ; con . add ( p a n e l 2 ) ; p a n e l 1 . add ( boton1 ) ; p a n e l 1 . setBackground (BLUE ) ; p a n e l 2 . add ( boton2 ) ; p a n e l 2 . add ( boton3 ) ; p a n e l 2 . setBackground (RED) ; s e t S i z e (ANCHO, ALTO) ;

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

} public s t a t i c void main ( S t r i n g [ ] a r g s ) { JFrameConJPanels ventana = new JFrameConJPanels ( ) ; ventana . s e t V i s i b l e ( true ) ; } }

C´ odigo 7: Aplicaci´on JFrameConJPanels. Al ejecutar la aplicaci´ on JFrameConJPanels se deben mostrar los dos JPanel que fueron agregados al JFrame, el primero con un bot´ on y color azul de fondo, y el otro con dos botones y color rojo de fondo. Cuando se crea un objeto JPanel, se puede usar uno de cuatro constructores disponibles. Los diferentes constructores permiten usar valores por defecto o indicar un manejador de dise˜ no y si el JPanel es doble b´ ufer. Si se indica doble b´ ufer, la cual es la estrategia de b´ ufer por defecto, se indica que el espacio de memoria adicional ser´a usado para dibujar el JPanel fuera de pantalla cuando sea actualizado. Con doble b´ ufer, un JPanel redibujado es mostrado s´olo cuando este est´a completo; esto proporciona al usuario con pantallas actualizadas que no parpadeen mientras son redibujadas. Los cuatro constructores son los siguientes: JPanel() crea un JPanel con doble b´ ufer y un dise˜ no de flujo. JPanel(boolean esDobleB´ ufer) crea un JPanel con un dise˜ no de flujo y la estrategia de doble b´ ufer indicada. JPanel(LayoutManager dise~ no) crea un JPanel con el manejador de dise˜ no indicado y doble b´ ufer. JPanel(LayoutManager dise~ no, boolean esDobleB´ ufer) crea un JPanel con el manejador de dise˜ no y la estrategia de b´ ufer indicados. Nota. Cuando se emplea doble b´ ufer, el ´area de pantalla visible es llamada el ´ area primaria, y la imagen fuera de pantalla es llamada el b´ ufer de respaldo. El acto de copiar los contenidos de una ´area a otra es frecuentemente referida como una transferencia lineal de bloques, o blitting. El doble b´ ufer previene la “despedazadera”, el efecto visual que ocurre cuando se ven partes de im´agenes diferentes porque el redibujado no es lo suficientemente r´apido. Como la mayor´ıa de las prestaciones, doble b´ ufer tiene un costo de requerimientos adicionales de memoria.

13

Hay varias formas para crear un JPanel que use un manejador BorderLayout: Se crea un dise˜ no con nombre y se usa este como un argumento en un constructor JPanel: BorderLayout borde = new BorderLayout(); JPanel miPanel = new JPanel(borde); Se usa un manejador de dise˜ no an´onimo con el constructor JPanel: JPanel miPanel = new JPanel(new BorderLayout()); Se crea un JPanel y luego se pone su manejador de dise˜ no usando el m´etodo setLayout(): JPanel miPanel = new JPanel(); miPanel.setLayout(new BorderLayout()); Cuando un JPanel tendr´ a un manejador diferente de FlowLayout, es preferible especificar el manejador de dise˜ no cuando se crea el JPanel por cuestiones de rendimiento. Si se crea el JPanel primero y luego se cambia su manejador, se crea un objeto FlowLayout innecesario para la instanciaci´ on original. Se agregan componentes a un JPanel con el m´etodo add(). La aplicaci´on JDemoMuchosPaneles, c´odigo 8, es un JFrame que contiene cuatro JPanel y doce JButton donde cada uno muestra un n´ umero con letras. Al panel de contenido de un JFrame autom´aticamente se le asigna un BorderLayout, y a cada JPanel se le asigna un GridLayout o un FlowLayout y son colocados en una de las regiones, dejando la regi´on norte vac´ıa. Uno o m´as JButton son luego colocados en cada JPanel. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

import j a v a . awt . ∗ ; import j a v a x . swing . ∗ ; public c l a s s JDemoMuchosPaneles extends JFrame { // Doce b o t o n e s private JButton boton01 = new JButton ( ”Uno” ) ; private JButton boton02 = new JButton ( ”Dos” ) ; private JButton boton03 = new JButton ( ” Tres ” ) ; private JButton boton04 = new JButton ( ” Cuatro ” ) ; private JButton boton05 = new JButton ( ” Cinco ” ) ; private JButton boton06 = new JButton ( ” S e i s ” ) ; private JButton boton07 = new JButton ( ” S i e t e ” ) ; private JButton boton08 = new JButton ( ”Ocho” ) ; private JButton boton09 = new JButton ( ”Nueve” ) ; private JButton boton10 = new JButton ( ” Diez ” ) ; private JButton boton11 = new JButton ( ”Once” ) ; private JButton boton12 = new JButton ( ” Doce ” ) ; // Cuatro p a n e l e s private JPanel p a n e l 0 1 = new JPanel (new GridLayout ( 2 , 0 ) ) ; private JPanel p a n e l 0 2 = new JPanel (new FlowLayout ( ) ) ; private JPanel p a n e l 0 3 = new JPanel (new FlowLayout ( ) ) ; private JPanel p a n e l 0 4 = new JPanel (new GridLayout ( 2 , 0 ) ) ; public JDemoMuchosPaneles ( ) { s e t L a y o u t (new BorderLayout ( ) ) ;

14

add ( panel01 , BorderLayout .WEST) ; add ( panel02 , BorderLayout .CENTER) ; add ( panel03 , BorderLayout .SOUTH) ; add ( panel04 , BorderLayout .EAST ) ; p a n e l 0 1 . add ( boton01 ) ; p a n e l 0 1 . add ( boton02 ) ; p a n e l 0 1 . add ( boton03 ) ; p a n e l 0 2 . add ( boton04 ) ; p a n e l 0 2 . add ( boton05 ) ; p a n e l 0 2 . add ( boton06 ) ; p a n e l 0 3 . add ( boton07 ) ; p a n e l 0 4 . add ( boton08 ) ; p a n e l 0 4 . add ( boton09 ) ; p a n e l 0 4 . add ( boton10 ) ; p a n e l 0 4 . add ( boton11 ) ; p a n e l 0 4 . add ( boton12 ) ; s e t S i z e (500 , 250);

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

} public s t a t i c void main ( S t r i n g [ ] a r g s ) { JDemoMuchosPaneles ventana = new JDemoMuchosPaneles ( ) ; ventana . s e t V i s i b l e ( true ) ; } }

C´ odigo 8: La aplicaci´on JDemoMuchosPaneles. Cuando se ejecuta la aplicaci´ on JDemoMuchosPaneles el usuario puede hacer la ventana horizontalmente m´as grande para observar como algunos botones aparecen y se reacomodan, en particular los que est´an en el JPanel que ocupa la regi´on central. Nota. Si se crea un programa con muchos botones y p´aneles como los del c´odigo 8, se deber´ıa preferir crear arreglos de los componentes en vez de manejar muchos nombres individualmente.

Nota. Los contenedores Swing, excepto JPanel, y los p´aneles de contenido proporcionan m´etodos interfaz de programaci´ on de aplicaciones (API) que se deber´ıan usar en vez del m´etodo add().

GridLayout proporciona renglones y columnas que son similares a los arreglos bidimensionales. Por lo tanto, este se usa para mostrar arreglos de objetos. La aplicaci´on Tablero, c´odigo 9, muestra un patr´on de ocho renglones y ocho columnas en colores alternantes. El JPanel colocado en el panel de contenido tiene un GridLayout de ocho por ocho. 64 JPanel son declarados, y en un ciclo, uno por uno, son instanciados y asignados a una secci´on de la cuadr´ıcula, l´ıneas 19—21. Despu´es de que cada conjunto de ocho JPanel es asignado a la cuadr´ıcula, cuando x es divisible por 8, el color1 y el color2 son intercambiados, para que el primer rengl´on inicie con un cuadro azul, el segundo inicie con un cuadro blanco, etc. Dentro de cada rengl´on, todos los cuadros con posici´on par son llenados con un color, y los otros cuadros con otro color. Ejecutar la aplicaci´on Tablero para ver la salida. 1 2 3

import j a v a . awt . ∗ ; import j a v a x . swing . ∗ ; public c l a s s T a b l e r o extends JFrame {

15

private private private private private private

f i n a l int RENS = 8 ; f i n a l int COLS = 8 ; f i n a l int SEP = 2 ; f i n a l int NUM = RENS ∗ COLS ; int x ; JPanel pane = new JPanel ( new GridLayout (RENS, COLS, SEP , SEP ) ) ; private JPanel [ ] p a n e l = new JPanel [NUM] ; private C o l o r c o l o r 1 = C o l o r .WHITE; private C o l o r c o l o r 2 = C o l o r .BLUE; private C o l o r tempColor ; public T a b l e r o ( ) { super ( ” T a b l e r o ” ) ; s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ; add ( pane ) ; f o r ( x = 0 ; x < NUM; ++x ) { p a n e l [ x ] = new JPanel ( ) ; pane . add ( p a n e l [ x ] ) ; i f ( x % COLS == 0 ) { tempColor = c o l o r 1 ; color1 = color2 ; c o l o r 2 = tempColor ; } i f ( x % 2 == 0 ) p a n e l [ x ] . setBackground ( c o l o r 1 ) ; else p a n e l [ x ] . setBackground ( c o l o r 2 ) ; } } public s t a t i c void main ( S t r i n g [ ] a r g s ) { T a b l e r o ventana = new T a b l e r o ( ) ; f i n a l int TAM = 3 0 0 ; ventana . s e t S i z e (TAM, TAM) ; ventana . s e t V i s i b l e ( true ) ; }

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

}

C´ odigo 9: Aplicaci´on Tablero. Cuando se crea la clase Tablero, se podr´ıa estar tentado a crear s´olo dos JPanel, uno azul y uno blanco, y agregarlo al panel de contenido varias veces. Sin embargo, cada componente GUI puede ser contenido una sola vez. Si un componente ya est´a en un contenedor y se intenta agregar otro contenedor, el componente ser´ a quitado del primer contenedo y luego agregado al segundo.

5.

JScrollPane

Cuando componentes en una UI Swing requieren m´as ´area de visualizaci´on que la les ha sido asignada, se puede usar un contenedor JScrollPane para tener los componentes en una forma que permitan al usuario desplazar partes no visibles inicialmente del panel en la vista. Un JScrollPane tiene barras de desplazamiento a un lado o en el fondo, o en ambos, con una ´area de visualizaci´ on

16

llamada una ventana (viewport). La siguiente figura muestra la jerarqu´ıa de herencia de la clase JScrollPane. java.lang.Object | +--java.awt.Component | +---java.awt.Container | +---javax.swing.JComponent | +---javax.swing.JScrollPanel Hay cuatro constructores JScrollPane que son: JScrollPane() crea un JScrollPane vac´ıo en el cual las barras de desplazamiento horizontal y vertical aparecen cuando se ocupan. JScrollPane(Component) crea un JScrollPane que muestra el contenido del componente indicado. JScrollPane(Component, int, int) crea un JScrollPane que muestra el componente especificado e incluye especificaciones de las barras de desplazamiento horizontal y vertical. JScrollPane(int, int) crea un JScrollPane con ambas especificaciones de las barras de desplazamiento horizontal y vertical. Cuando se crea un panel de desplazamiento simple usando el constructor sin argumentos, como en el siguiente ejemplo, las barras de desplazamiento horizontal y vertical aparecen solo si se ocupan, es decir, si el contenido del panel no puede ser mostrado completamente: JScrollPane unScrollPane = new JScrollPane(); Para forzar la aparici´ on de una barra de desplazamiento, se pueden usar las constantes definidas en la interfaz JScrollPaneConstants: ScrollPaneConstants.HORIZONTAL SCROLLBAR AS NEEDED ScrollPaneConstants.HORIZONTAL SCROLLBAR ALWAYS ScrollPaneConstants.HORIZONTAL SCROLLBAR NEVER ScrollPaneConstants.VERTICAL SCROLLBAR AS NEEDED ScrollPaneConstants.VERTICAL SCROLLBAR ALWAYS ScrollPaneConstants.VERTICAL SCROLLBAR NEVER El siguiente c´ odigo crea un panel de desplazamiento que muestra una imagen llamada dibujo, una barra de desplamiento vertical, y sin barra de desplazamiento horizontal: 17

JScrollPane desplaza = new JScrollPane(dibujo, ScrollPaneConstants.VERTICAL SCROLLBAR ALWAYS, ScrollPaneConstants.HORIZONTAL SCROLLBAR NEVER); La aplicaci´on DemoJScroll, c´ odigo 10, tiene una etiqueta con una fuente grande que se agreg´ oa un panel. El panel de desplazamiento llamado desplaza incluye el panel y dos barras de desplazamiento. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

import j a v a . awt . ∗ ; import j a v a x . swing . ∗ ; public c l a s s DemoJScroll extends JFrame { private JPanel p a n e l = new JPanel ( ) ; private J S c r o l l P a n e d e s p l a z a = new J S c r o l l P a n e ( panel , S c r o l l P a n e C o n s t a n t s .VERTICAL SCROLLBAR ALWAYS, S c r o l l P a n e C o n s t a n t s .HORIZONTAL SCROLLBAR ALWAYS ) ; private JLabel l a b e l = new JLabel ( ” Hace o c h e n t a y s i e t e ” ) ; private Font fontGrande = new Font ( ” A r i a l ” , Font . PLAIN , 3 0 ) ; private C o n t a i n e r con ; public DemoJScroll ( ) { super ( ” DemoJScroll ” ) ; s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ; con = getContentPane ( ) ; l a b e l . s e t F o n t ( fontGrande ) ; con . add ( d e s p l a z a ) ; p a n e l . add ( l a b e l ) ; } public s t a t i c void main ( S t r i n g [ ] a r g s ) { f i n a l int ANCHO = 1 8 0 ; f i n a l int ALTO = 1 0 0 ; DemoJScroll unaVentana = new DemoJScroll ( ) ; unaVentana . s e t S i z e (ANCHO, ALTO) ; unaVentana . s e t V i s i b l e ( true ) ; } }

C´ odigo 10: Aplicaci´on DemoJScroll. El objeto DemoJScroll en el programa del c´odigo 10 es puesto a prop´osito con un tama˜ no suficientemente peque˜ no (180x100) as´ı una sola parte de la etiqueta que contiene es visible a la vez. Un usuario puede deslizar las barras de desplazamiento para ver la etiqueta completa. Al ejecutar la aplicaci´on DemoJScroll muestra la ventana con barras de desplazamiento en dos lugares.

6.

Eventos y su manejo

La clase padre de todos los eventos es EventObject, la cual desciende de la clase Object. EventObject es el padre de AWTEvent, la cual a su vez es el padre de clases de eventos espec´ıficos como ActionEvent e ItemEvent. La clase abstracta AWTEvent est´a contenida en el paquete java.awt.event. La siguiente figura ilustra la jerarqu´ıa de herencia de estas relaciones.

18

java.lang.Object | +--java.util.EventObject | +---java.awt.AWTEvent | +---java.awt.event.ActionEvent +---java.awt.event.AdjustmentEvent +---java.awt.event.ItemEvent +---java.awt.event.TextEvent +---java.awt.event.ComponentEvent | +---java.awt.event.ContainerEvent +---java.awt.event.FocusEvent +---java.awt.event.PaintEvent +---java.awt.event.WindowEvent +---java.awt.event.InputEvent | +---java.awt.event.KeyEvent +---java.awt.event.MouseEvent En la figura previa, ComponentEvent es padre de varias clases de evento, incluyendo a InputEvent, la cual es padre de KeyEvent y MouseEvent. El ´arbol para eventos tiene descendencia que va lejos, pero los nombres de las clases son simples, y comparten tareas b´asicas dentro de los programas. Por ejemplo, ActionEvent son generados por componentes donde los usuarios pueden pulsar, como JButton y JCheckBox; TextEvent son generados por componentes en los cuales el usuario ingresa texto, tales como JTextField. MouseEvent incluyen determinar la posici´on del apuntador del rat´ on y la distinci´on entre una pulsaci´ on simple y una doble. El cuadro 3 lista algunas acciones comunes del usuario y los eventos que son generados por ellos. Acci´ on del usuario Pulsar un bot´ on Pulsar un componente Pulsar un elemento en un cuadro de lista Pulsar un elemento en una casilla de verificaci´ on Cambiar texto en un campo de texto Abrir una ventana Iconificar una ventana Presionar una tecla

Tipo de evento resultante ActionEvent MouseEvent ItemEvent ItemEvent TextEvent WindowEvent WindowEvent KeyEvent

Cuadro 3: Ejemplos de acciones del usuario y sus tipos de eventos resultantes. Como ActionEvent involucra al rat´ on, es f´acil confundirlo con MouseEvent. Si se est´a interesado en ActionEvent, la atenci´ on est´ a en los cambios de un componente, por ejemplo, un JButton en un JFrame siendo presionado; si se est´ a interesado en MouseEvent, el foco est´a en lo que el usuario hace manualmente con el rat´ on, por ejemplo, pulsar el bot´on izquierdo del rat´on.

19

Cuando se escriben programas con GUI, siempre se est´an manejando eventos que se originan con el rat´on o teclas en componentes o contenedores espec´ıficos. El sistema operativo notifica al usuario cuando un AWTEvent ocurre, por ejemplo, cuando el rat´on es pulsado. Se pueden ignorar los AWTEvent, y por lo tanto no producir´ an alg´ un efecto. Para tener cuidado de los eventos se puede implementar una interfaz apropiada para la clase. Cada clase evento mostrada en el cuadro 3 tiene una interfaz receptora asociada con este, as´ı para cada clase evento, Evento, hay una interfaz similar llamada Listener. Por ejemplo, ActionEvent tiene una interfaz ActionListener. La clase MouseEvent tiene un receptor adicional adem´as de MouseListener que es MouseMotionListener. Cada m´etodo de la interfaz Listener tiene el tipo de regreso void, y cada uno toma un argumento: un objeto que es una instancia de la correspondiente clase Evento. As´ı, la interfaz ActionListener tiene un m´etodo manejador de evento llamado actionPerformed(), y su cabecera es void actionPerformed(ActionEvent e). Cuando una acci´on sucede, el m´etodo actionPerformed() se ejecuta, y e representa una instancia de aquel evento. En vez de implementar una clase receptora, se puede extender una clase adaptadora. Una clase adaptadora implementa todos los m´etodos en una interfaz, con un cuerpo vac´ıo para cada m´etodo. Por ejemplo, la clase MouseAdapter da un m´etodo vac´ıo para todos los m´etodos contenidos en MouseListener. La ventaja de extender una clase adaptadora en vez de implementar una interfaz receptora es que s´ olo se necesita escribir los m´etodos que se quieren usar. Si un receptor tiene un s´olo m´etodo, no hay necesidad de un adaptador, como con ActionListener. Si se usa un receptor o un adaptador, se crea un manejador de evento cuando se escribe c´odigo para los m´etodos receptores; es decir, se le dice a la clase como manejar el evento. Despu´es de crear el manejador, se debe registrar una instancia de la clase con el componente que se quiere que el evento afecte. Para cualquier Listener, se debe usar la forma object.addListener(Component) para registrar un objeto con el Component que escuchar´a objetos. Los m´etodos addListener(), tales como addActionListener() y addItemListener(), todos trabajan de la misma forma. Ellos registran un receptor con un Component, regresan void, y toman un objeto Listener como un argumento. Por ejemplo, si un JFrame es un ActionListener y contiene un JButton llamado presi´ oname, entonces la siguiente sentencia registra este JFrame como un receptor para el JButton presi´ oname: presi´ oname.addActionListener(this); El cuadro 4 lista los eventos con sus receptores y manejadores.

Ejemplo de manejo-evento KeyListener Se usa la interfaz KeyListener cuando se est´a interesado en acciones que el usuario inicia desde el teclado. La interfaz KeyListener contiene tres m´etodos: keyPressed(), keyTyped(), y keyReleased(). Para la mayor´ıa de las aplicaciones de teclado, no es importante si se realiza la acci´on cuando el usuario primero presiona una tecla, durante la presi´on de la tecla, o hasta que la tecla sea soltada; probablemente estos eventos ocurren en secuencia r´apida. Sin embargo, en aquellas ocasiones que no se quiere tomar acci´on mientras el usuario mantiene presionada la 20

Evento ActionEvent ItemEvent TextEvent AdjustmentEvent

Receptor(es) ActionListener ItemListener TextListener AdjustmentListener

ContainerEvent

ContainerListener

ComponentEvent

ComponentListener

FocusEvent

FocusListener

MouseEvent

MouseListener MouseMotionListener

KeyListener

KeyEvent

WindowEvent

WindowListener

MouseWheelEvent

MouseWheelListener

Manejador(es) actionPerformed(ActionEvent) itemStateChanged(ItemEvent) textValueChanged(TextEvent) adjustmentValueChanged(AdjustmentEvent) componentAdded(ContainerEvent) componentRemoved(ContainerEvent) componentMoved(ComponentEvent) componentHidden(ComponentEvent) componentResized(ComponentEvent) componentShown(ComponentEvent) focusGained(FocusEvent) focusLost(FocusEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mouseClicked(MouseEvent) mouseDragged(MouseEvent) mouseMoved(MouseEvent) keyPressed(KeyEvent) keyTyped(KeyEvent) keyReleased(KeyEvent) windowActivated(WindowEvent) windowClosing(WindowEvent) windowClosed(WindowEvent) windowDeiconified(WindowEvent) windowIconified(WindowEvent) windowOpened(WindowEvent) mouseWheelMoved(MouseWheelEvent)

Cuadro 4: Ejemplos de acciones del usuario y sus tipos de eventos resultantes.

21

tecla, se pueden colocar las acciones en el m´etodo keyReleased(). Lo mejor es usar el m´etodo keyTyped() cuando se quiere descubrir que car´acter fue tecleado. Cuando el usuario presiona una tecla que no genera un car´ acter, tal como una tecla funci´on, llamadas a veces una tecla acci´ on, keyTyped() no es ejecutada. Los m´etodos keyPressed() y keyReleased() dan las u ´nicas formas para obtener informaci´ on acerca de las teclas que no generan caracteres. La clase KeyEvent tiene constantes conocidas como c´ odigos de teclas virtuales que representan las teclas que han sido presionadas. Por ejemplo, cuando se teclea A, dos c´odigos de teclas virtuales son generados: Cambio y “a”. Las constantes de c´ odigos de teclas virtuales tienen nombres como VK SHIFT y VK ALT. La aplicaci´on DemoJKeyFrame, c´ odigo 11 usa el m´etodo keyTyped() para saber cual fue la u ´ltima tecla presionada por el usuario. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

import j a v a . awt . ∗ ; import j a v a . awt . e v e n t . ∗ ; import j a v a x . swing . ∗ ; public c l a s s DemoJKeyFrame extends JFrame implements K e y L i s t e n e r { private JLabel a v i s o = new JLabel ( ” P r e s i o n a r t e c l a s en e l campo de t e x t o : ” ) ; private JLabel e t i q u e t a S a l i d a = new JLabel ( ) ; private J T e x t F i e l d t e x t F i e l d = new J T e x t F i e l d ( 1 0 ) ; public DemoJKeyFrame ( ) { s e t T i t l e ( ”Marco DemoJKeyFrame” ) ; s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ; add ( a v i s o , BorderLayout .NORTH) ; add ( t e x t F i e l d , BorderLayout .CENTER) ; add ( e t i q u e t a S a l i d a , BorderLayout .SOUTH) ; t e x t F i e l d . addKeyListener ( this ) ; } public void keyTyped ( KeyEvent e ) { char c = e . getKeyChar ( ) ; ´ ltima t e c l a presionada : ” + c ) ; e t i q u e t a S a l i d a . s e t T e x t ( ”U } public void k e y P r e s s e d ( KeyEvent e ) { } public void k e y R e l e a s e d ( KeyEvent e ) { } public s t a t i c void main ( S t r i n g [ ] a r g s ) { DemoJKeyFrame ventanaKey = new DemoJKeyFrame ( ) ; f i n a l int ANCHO = 2 5 0 ; f i n a l int ALTO = 1 0 0 ; ventanaKey . s e t S i z e (ANCHO, ALTO) ; ventanaKey . s e t V i s i b l e ( true ) ; } }

C´ odigo 11: Aplicaci´on DemoJKeyFrame.

Nota. Los programadores Java llaman a los eventos keyTyped() eventos de “nivel–alto” porque no dependen de la plataforma o el dise˜ no del teclado. En cambio, los eventos keyPressed() y keyReleased() son eventos “nivel–bajo” y dependen de la plataforma y el dise˜ no del teclado

Al ejecutar la aplicaci´ on DemoJKeyFrame se muestra un indicador en el ´area del borde norte que pide al usuario teclear en el campo de texto del ´area central. Con cada tecla presionada, el m´etodo keyTyped() cambia la etiqueta en el a´rea de borde sur del marco para mostrar la tecla que fue generada por el KeyEvent m´ as reciente. 22

7.

M´ etodos de la clase AWTEvent

Adem´as de los m´etodos manejadores incluidos con las interfaces receptoras de eventos, las clases AWTEvent por s´ı mismas contienen otros m´etodos que devuelven informaci´on acerca de un evento. Por ejemplo, la clase ComponentEvent tiene el m´etodo getComponent() que permite determinar cual de los m´ ultiples Component gener´ o el evento. La clase WindowEvent tiene un m´etodo similar, getWindow(), que devuelve la Window que es la fuente de un evento. El cuadro 5 lista algunos m´etodos u ´tiles para varias clases de eventos. Todos los Component tienen estos m´etodos: addComponentListener() addFocusListener() addMouseListener() addMouseMotionListener() Se puede llamar cualquiera de los m´etodos listados en el cuadro 5 usando el formato objeto-puntom´etodo que se usa con todos los m´etodos de instancia. Por ejemplo, si se tiene un KeyEvent llamado eventoEntrada y un entero llamado valorUnicode, la siguiente sentencia es v´alida: valorUnicode = eventoEntrada.getKeyChar(); Cuando se usa un evento, se puede usar cualquiera de los m´etodos de evento, y por la herencia, se pueden tambi´en usar m´etodos que pertenezcan a cualquier superclase del evento. Por ejemplo, cualquier KeyEvent tiene acceso a los m´etodos InputEvent, ComponentEvent, AWTEvent, EventObject, y Object, al igual que los m´etodos KeyEvent.

Coordenadas x e y El cuadro 5 refiere las coordenadas x-y de un apuntador de rat´on. Una ventana o marco consiste de una cantidad de p´ıxeles horizontales y verticales en la pantalla. Cualquier componente que se ponga en la pantalla tiene un posici´ on horizontal, o eje x al igual que una posici´on vertical, eje y en la ventana. La esquina superior izquierda de cualquier pantalla es la posici´on 0,0. El primer valor, o coordenada x, se incrementa conforme se viaja de izquierda a derecha a trav´es de la ventana. El segundo valor, coordenada y, se incrementa conforme se va de arriba hacia abajo.

8.

Manejo de eventos del rat´ on

La interfaz MouseMotionListener proporciona los m´etodos llamados mouseDragged() y mouseMoved() que detectan el rat´ on siendo movido o arrastrando a trav´es de una superficie componente. La interfaz MouseListener da los m´etodos mousePressed(), mouseClicked(), y mouseReleased() que son an´alogos a los m´etodos evento teclado keyPressed(), keyTyped(), y keyReleased()

23

Clase EventObject

M´ etodo Object getSource()

ComponentEvent

Component getComponent()

WindowEvent

Window getWindow()

ItemEvent

Object getItem() int getStateChange()

InputEvent

int getModifiers() int getWhen() boolean isAltDown() boolean isControlDown() boolean isShiftDown()

KeyEvent

getKeyChar()

MouseEvent

getButton()

getClickCount()

int getX() int getY() Point getPoint()

Prop´ osito Regresa la referencia Object involucrada en el evento. Regresa la referencia Component involucrada en el evento. Regresa la referencia Window involucrada en el evento. Regresa la referencia Object que fue seleccionada o deseleccionada. Regresa un entero llamado ItemEvent.SELECTED o ItemEvent.DESELECTED. Regresa un entero para indicar cual bot´on del rat´on fue pulsado. Regresa un tiempo indicando cuando el evento ocurri´o. Regresa si la tecla Alt fue presionada cuando el evento ocurri´o. Regresa si la tecla Ctrl fue presionada cuando el evento ocurri´o. Regresa si la tecla Shift fue presionada cuando el evento ocurri´o. Regresa el car´acter Unicode ingresado del teclado. Regresa cual, si hay alguno, de los botones del rat´on ha cambido, usa los campos NOBUTTON, BUTTON1, BUTTON2, y BUTTON3. Regresa el n´ umero de pulsaciones del rat´on; permite identificar las dobles pulsaciones del usuario. Regresal la coordenada x del apuntador del rat´on. Regresal la coordenada y del apuntador del rat´on. Regresa el objeto Point que contiene las coordenadas x e y del lugar del rat´on.

Cuadro 5: M´etodos u ´tiles de clases de eventos.

24

respectivamente. Sin embargo, con un rat´on se est´a m´as interesado que s´olo el bot´on presionado; en ocasiones se quiere saber a d´ onde el rat´on apunta. Los m´etodos adicionales de la interfaz mouseEntered() y mouseExited() informan cuando el usuario posiciona el rat´on encima de un componente o mueve el rat´ on fuera de un componente. La interfaz MouseInputListener implementa todos los m´etodos de las interfaces MouseListener y MouseMotionListener; sin embargo no tiene m´etodos propios, pero es conveniente cuando se quiere manejar muchos tipos diferentes de eventos de rat´ on. Los cuadros 6 y 7 muestran los m´etodos de las clases MouseListener y MouseMotionListener, respectivamente. M´ etodo void mouseClicked(MouseEvent e)

void mouseEntered(MouseEvent e) void mouseExited(MouseEvent e) void mousePressed(MouseEvent e) void mouseReleased(MouseEvent e)

Descripci´ on Invocado cuando el bot´on del rat´on ha sido pulsado (presionado y soltado) en un componente. Invocado cuando el apuntador del rat´on ingresa en un componente. Invocado cuando el apuntador del rat´on sale de un componente. Invocado cuando un bot´on del rat´on ha sido presionado en un componente. Invocado cuando un bot´on del rat´on ha sido soltado en un componente.

Cuadro 6: M´etodos MouseListener. M´ etodo void mouseDragged(MouseEvent e)

void mouseMoved(MouseEvent e)

Descripci´ on Invocado cuando el apuntador del rat´on es presionado en un componente y luego arrastrado. Invocado cuando el apuntador del rat´on ha sido movido en un componente pero sin alg´ un bot´on presionado.

Cuadro 7: M´etodos MouseMotionListener. Nota. La interfaz MouseWheelListener tiene s´olo un m´etodo llamado mouseWheelMoved(), y este acepta un argumento MouseWheelEvent.

Cada uno de los m´etodos de los cuadros 6 y 7 aceptan un argumento MouseEvent. Un MouseEvent es el tipo de evento generado por la manipulaci´on del rat´on. En la siguiente figura se muestra la jerarqu´ıa de herencia de la clase MouseEvent. De ese diagrama, se puede ver que un MouseEvent es un tipo de InputEvent, el cual es un tipo de ComponentEvent. La clase MouseEvent contiene muchos m´etodos de instancia y campos que son u ´tiles en describir eventos generados por el rat´ on. El cuadro 8 lista algunos de los m´etodos m´as u ´tiles de la clase MouseEvent, y el cuadro 9 lista algunos campos.

25

java.lang.Object | +--java.util.EventObject | +---java.awt.AWTEvent | +---java.awt.event.ComponentEvent | +---java.awt.event.InputEvent | +---java.awt.event.MouseEvent

M´ etodo int getButton()

int getClickCount() int getX() int getY()

Descripci´ on Regresa cual, si hay, de los botones del rat´on ha cambiado su estado; usa los campos NOBUTTON, BUTTON1, BUTTON2, y BUTTON3. Regresa la cantidad de pulsaciones del rat´on asociado con el evento actual. Regresa la posici´on-x horizontal del evento relativa al componente fuente. Regresa la posici´on-y vertical del evento relativa al componente fuente.

Cuadro 8: M´etodos u ´tiles de la clase MouseEvent. Campo static int BUTTON1 static int BUTTON2 static int BUTTON3 static int NOBUTTON static static static static

int int int int

MOUSE MOUSE MOUSE MOUSE

CLICKED DRAGGED ENTERED EXITED

Descripci´ on Indica bot´on de rat´on #1; usado getButton(). Indica bot´on de rat´on #2; usado getButton(). Indica bot´on de rat´on #3; usado getButton(). Indica ning´ un bot´on de rat´on; usado getButton(). El evento “rat´on pulsado”. El evento “rat´on arrastrado”. El evento “rat´on ingresado”. El evento “rat´on salido”.

por por por por

Cuadro 9: Algunos campos u ´tiles de la clase MouseEvent. La aplicaci´on JFrameMouseAction, c´ odigo 12, muestra varios de los m´etodos receptores y de eventos del rat´on. JFrameMouseAction extiende JFrame, y como implementa la interfaz MouseListener, debe incluir todos los cinco m´etodos—mouseClicked(), mouseEntered(), mouseExited(), mousePressed(), y mouseReleased()—a pesar de que no hay acciones incluidas en los m´etodos mousePressed() y mouseReleased().

26

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

import j a v a . awt . ∗ ; import j a v a . awt . e v e n t . ∗ ; import j a v a x . swing . ∗ ; import s t a t i c j a v a . awt . e v e n t . MouseEvent . ∗ ; public c l a s s JFrameMouseAction extends JFrame implements M o u s e L i s t e n e r { private int x , y ; private JLabel e t i q u e t a = new JLabel ( ” Haciendo a l g o con e l r a t ´on” ) ; S t r i n g mensj = ” ” ; public JFrameMouseAction ( ) { s e t T i t l e ( ” A c c i o n e s d e l Rat´on” ) ; s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ; s e t L a y o u t (new FlowLayout ( ) ) ; addMouseListener ( t h i s ) ; add ( e t i q u e t a ) ; } public void mouseClicked ( MouseEvent e ) { int cualBoton = e . getButton ( ) ; mensj = ” Se p r e s i o n ´ o el ” ; i f ( cualBoton == BUTTON1) mensj += ” bot´ on 1 . ” ; e l s e i f ( cualBoton == BUTTON2) mensj += ” bot´ on 2 . ” ; else mensj += ” bot´ on 3 . ” ; mensj += ” Se e s t ´ a en l a p o s i c i ´on ” + e . getX ( ) + ” , ” + e . getY ( ) + ” . ” ; i f ( e . g e t C l i c k C o u n t ( ) == 2 ) mensj += ” Hizo una d o b l e p u l s a c i ´on . ” ; else mensj += ” Hizo una p u l s a c i ´on s i m p l e . ” ; e t i q u e t a . s e t T e x t ( mensj ) ; } public void mouseEntered ( MouseEvent e ) { mensj = ” Se e n t r ´ o a l marco . ” ; e t i q u e t a . s e t T e x t ( mensj ) ; } public void mouseExited ( MouseEvent e ) { mensj = ” Se s a l i ´ o d e l marco . ” ; e t i q u e t a . s e t T e x t ( mensj ) ; } public void mousePressed ( MouseEvent e ) { } public void mouseReleased ( MouseEvent e ) { } public s t a t i c void main ( S t r i n g [ ] a r g s ) { JFrameMouseAction ventana = new JFrameMouseAction ( ) ; f i n a l int ANCHO = 7 5 0 ; f i n a l int ALTO = 3 0 0 ; ventana . s e t S i z e (ANCHO, ALTO) ; ventana . s e t V i s i b l e ( true ) ; } }

C´ odigo 12: La aplicaci´on JFrameMouseAction. Al ejecutar la aplicaci´ on JFrameMouseAction muestra mensaje conforme el usuario genera acciones 27

del rat´on. Al inicio de la clase, en la l´ınea 6, dos enteros son declarados para guardar las coordenadas x-y de la posici´ on del rat´ on. Un JLabel y un String son tambi´en declarados, en las l´ıneas 7 y 8, para guardar mensajes que informan al usuario de las acciones hechas con el rat´on. El constructor, l´ıneas 9–15, pone el t´ıtulo del JFrameMouseAction, pone la operaci´on de cierra, pone el manejador de dise˜ no, habilita al marco para escuchar los eventos del rat´on, y agrega el JLabel al JFrame. La mayor´ıa de las acciones ocurren en el m´etodo mouseClicked(). En este m´etodo se construye un String que al final es asignado al JLabel. Las mismas acciones podr´ıan haber sido colocadas en el m´etodo mousePressed() o mouseReleased(). Dentro del m´etodo mouseClicked(), el objeto MouseEvent llamado e es usado varios veces. Se usa con el m´etodo getButton() para determinar cual bot´on del rat´ on el usuario ha pulsado, con getX() y getY() para recuperar la posici´on del rat´on donde se puls´ o, y con getClickcount() para distinguir entre una pulsaci´on simple y una doble. El usuario es notificado cuando el apuntador del rat´on ha “entrado” al JFrame, y tambi´en cuando ha “salido” mediante mensajes diferentes generados por los m´etodos mouseEntered() y mouseExited() respectivamente. El m´etodo main() al final de la clase crea una instancia de la clase JFrameMouseAction y fija su tama˜ no y visibilidad.

9.

Uso de men´ us

Los men´ us son listas de opciones; estas son caracter´ısticas agregadas en programas GUI. Las aplicaciones de usuario son usadas para ver una barra de men´ u horizontal a lo largo de la parte superior del marco, y se espera que se puedan pulsar estas opciones para producir listas descendentes que muestran m´ as opciones. La lista horizontal de varias JMenu es una JMenuBar. Cada JMenu puede contener opciones, llamadas JMenuItems, o puede contener submen´ us que tambi´en son JMenu. La aplicaci´on JFrameMenu, c´ odigo 13, muestra un JFrame que muestra el uso de los siguientes componentes: Un JMenuBar que contiene dos JMenu llamados archivo y colores. Tres elementos dentro del JMenu colores: claro, oscuro, blanco. oscuro y blanco son JMenuItems. claro es un JMenu que tiene un submenu. Se puede decir que claro es un submen´ u porque una flecha est´ a a la derecha de su nombre, y cuando el rat´on se pone encima de claro, dos JMenuItem adicionales aparecen: rosa y amarillo. Para generar la salida dada por la ejecuci´on de la aplicaci´on JFrameMenu, un conjunto de objetos JMenuBar, JMenu, y JMenuItem fueron creados y puestos juntos en etapas. Se crean cada uno de los componentes como sigue: 1. Crear un JMenuBar: JMenuBar BarraPrinc = new JMenuBar(); 2. Crear los dos JMenu que son parte del JMenuBar: 28

JMenu archivo = new JMenu("Archivo"); JMenu colores = new JMenu("Colores"); 3. Los tres componentes dentro del JMenu colores son creados como sigue: JMenu claro = new JMenu("Claro"); JMenuItem oscuro = new JMenuItem("Oscuro"); JMenuItem blanco = new JMenuItem("Blanco"); 4. Los dos JMenuItem que son partes del JMenu Claro son creados as´ı: JMenuItem rosa = new JMenuItem("Rosa"); JMenuItem amarillo = new JMenuItem("Amarillo"); 5. Despu´es de que los componentes son creados, se ensamblan. Se agrega el JMenuBar a un JFrame usando el m´etodo setJMenuBar() como sigue: setJMenuBar(BarraPrinc); Usando el m´etodo setJMenuBar() asegura que la barra de men´ u es anclada a la cima del marco y parece una barra de men´ u convencional. Observar que el JMenuBar no es agregado al panel de contenido del JFrame; este es agregado al JFrame por s´ı mismo. 6. Los JMenu son agregados al JMenuBar usando el m´etodo add(). Por ejemplo: BarraPrinc.add(archivo); BarraPrinc.add(colores); 7. Un submen´ u y dos JMenuItem son agregados al men´ u colores como se muestra enseguida: colores.add(claro); colores.add(oscuro); colores.add(blanco); 8. Un submen´ u puede contener sus propios JMenuItem. Por ejemplo, el JMenu claro que es parte del men´ u colores contiene sus dos objetos propios JMenuItem: claro.add(rosa); claro.add(amarillo); El c´odigo 13 muestra un programa completo que crea un marco con un saludo y el JMenu descrito previamente.

29

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

import j a v a . awt . ∗ ; import j a v a . awt . e v e n t . ∗ ; import j a v a x . swing . ∗ ; public c l a s s JFrameMenu extends JFrame implements A c t i o n L i s t e n e r { private JMenuBar B a r r a P r i n c = new JMenuBar ( ) ; private JMenu a r c h i v o = new JMenu ( ” Archivo ” ) ; private JMenu c o l o r e s = new JMenu ( ” C o l o r e s ” ) ; private JMenuItem s a l i r = new JMenuItem ( ” S a l i r ” ) ; private JMenu c l a r o = new JMenu ( ” C l a r o ” ) ; private JMenuItem o s c u r o = new JMenuItem ( ” Oscuro ” ) ; private JMenuItem b l a n c o = new JMenuItem ( ” Blanco ” ) ; private JMenuItem r o s a = new JMenuItem ( ” Rosa ” ) ; private JMenuItem a m a r i l l o = new JMenuItem ( ” A m a r i l l o ” ) ; private JLabel e t i q u e t a = new JLabel ( ” Hola ” ) ; public JFrameMenu ( ) { s e t T i t l e ( ” Demostraci´ on de Men´ u” ) ; s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ; s e t L a y o u t (new FlowLayout ( ) ) ; setJMenuBar ( B a r r a P r i n c ) ; B a r r a P r i n c . add ( a r c h i v o ) ; B a r r a P r i n c . add ( c o l o r e s ) ; a r c h i v o . add ( s a l i r ) ; c o l o r e s . add ( c l a r o ) ; c o l o r e s . add ( o s c u r o ) ; c o l o r e s . add ( b l a n c o ) ; c l a r o . add ( r o s a ) ; c l a r o . add ( a m a r i l l o ) ; s a l i r . addActionListener ( this ) ; oscuro . addActionListener ( this ) ; blanco . addActionListener ( this ) ; rosa . addActionListener ( this ) ; amarillo . addActionListener ( this ) ; add ( e t i q u e t a ) ; e t i q u e t a . s e t F o n t (new Font ( ” A r i a l ” , Font .BOLD, 2 6 ) ) ; } public void a c t i o n P e r f o r m e d ( ActionEvent e ) { Object s o u r c e = e . g e t S o u r c e ( ) ; C o n t a i n e r con = getContentPane ( ) ; i f ( s o u r c e == s a l i r ) System . e x i t ( 0 ) ; e l s e i f ( s o u r c e == o s c u r o ) con . setBackground ( C o l o r .BLACK) ; e l s e i f ( s o u r c e == b l a n c o ) con . setBackground ( C o l o r .WHITE) ; e l s e i f ( s o u r c e == r o s a ) con . setBackground ( C o l o r . PINK ) ; else con . setBackground ( C o l o r .YELLOW) ; } public s t a t i c void main ( S t r i n g [ ] a r g s ) { JFrameMenu ventana = new JFrameMenu ( ) ; f i n a l int ANCHO = 2 5 0 ; f i n a l int ALTURA = 2 0 0 ; ventana . s e t S i z e (ANCHO, ALTURA) ; ventana . s e t V i s i b l e ( true ) ; } 30 }

C´ odigo 13: La aplicaci´on JFrameMenu.

En la aplicaci´ on JFrameMenu, cada JMenuItem se convierte en una fuente para una ActionEvent, y al JFrame se le asigna el papel de receptor para cada uno. El m´etodo actionPerformed() determina la fuente de cualquier evento generado. Si el usuario selecciona la opci´on Salir del men´ u Archivo, la aplicaci´on termina. Si el usuario selecciona cualquiera de los colores del men´ u Colores, el color del fondo del JFrame es modificado en consecuencia.

Uso de objetos JCheckBoxMenuItem y JRadioButtonMenuItem Las clases JCheckBoxMenuItem y JRadioButtonMenuItem derivan de la clase JMenuItem. Cada una proporciona elementos de men´ u m´ as espec´ıficos como sigue: Los objetos JCheckBoxMenuItem aparecen seguido de una casilla de verificaci´on. Un elemento puede ser seleccionado, mostrando una marca de verificaci´on en la casilla, o no. Se usan los elementos de casilla de verificaci´ on para apagar o encender opciones. Los objetos JRadioButtonMenuItem aparecen seguidos de un bot´on circular de radio. Se espera que los botones de radio sean mutuamente excluyentes, as´ı que se hacen parte de un ButtonGroup. Luego, cuando cualquiera de los botones de radio es seleccionado, todos los otros no quedan seleccionados. El estado de un JCheckBoxMenuItem o un JRadioButtonMenuItem puede ser determinado con el m´etodo isSelected(), y se puede modificar el estado de la casilla de verificaci´on con el m´etodo setSelected(). La aplicaci´on JFrameMenu2, c´ odigo 14, muestra dos JCheckBoxMenuItem y tres JRadioButtonMenuItem han sido agregados a un JMenu. A los controles no se les ha asignado todav´ıa alguna tarea.

31

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

import j a v a . awt . ∗ ; import j a v a . awt . e v e n t . ∗ ; import j a v a x . swing . ∗ ; public c l a s s JFrameMenu2 extends JFrame { private JMenuBar B a r r a P r i n c = new JMenuBar ( ) ; private JMenu menu1 = new JMenu ( ” Archivo ” ) ; private JCheckBoxMenuItem v e r i f i c a 1 = new JCheckBoxMenuItem ( ” Marcar c a j a A” , true ) ; private JCheckBoxMenuItem v e r i f i c a 2 = new JCheckBoxMenuItem ( ” Marcar c a j a B” ) ; private JRadioButtonMenuItem r a d i o 1 = new JRadioButtonMenuItem ( ” Radio o p c i ´on 1 ” , true ) ; private JRadioButtonMenuItem r a d i o 2 = new JRadioButtonMenuItem ( ” Radio o p c i ´on 2 ” ) ; private JRadioButtonMenuItem r a d i o 3 = new JRadioButtonMenuItem ( ” Radio o p c i ´on 3 ” ) ; private ButtonGroup grupo = new ButtonGroup ( ) ; public JFrameMenu2 ( ) { s e t T i t l e ( ” Demostraci´ on de Men´ u s −− 2 ” ) ; s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ; s e t L a y o u t (new FlowLayout ( ) ) ; setJMenuBar ( B a r r a P r i n c ) ; B a r r a P r i n c . add ( menu1 ) ; menu1 . add ( v e r i f i c a 1 ) ; menu1 . add ( v e r i f i c a 2 ) ; menu1 . a d d S e p a r a t o r ( ) ; menu1 . add ( r a d i o 1 ) ; menu1 . add ( r a d i o 2 ) ; menu1 . add ( r a d i o 3 ) ; grupo . add ( r a d i o 1 ) ; grupo . add ( r a d i o 2 ) ; grupo . add ( r a d i o 3 ) ; }

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

public s t a t i c void main ( S t r i n g [ ] a r g s ) { JFrameMenu2 ventana = new JFrameMenu2 ( ) ; f i n a l int ANCHO = 3 0 0 ; f i n a l int ALTO = 2 0 0 ; ventana . s e t S i z e (ANCHO, ALTO) ; ventana . s e t V i s i b l e ( true ) ; } }

C´ odigo 14: Aplicaci´on JFrameMenu2.

Uso de addSeparator() Al ejecutar la aplicaci´ on JFrameMenu2 y pulsar en la opci´on Archivo del men´ u, se observa una l´ınea horizontal que separa en grupos las opciones. Este separador es agregado usando el m´etodo addSeparator() en la l´ınea 27 del c´ odigo 14. El separador no cambia la funcionalidad del men´ u; simplemente hace el m´enu m´ as organizado visualmente para el usuario. 32

Uso de setMnemonic() Un mnem´ onico ´ o nem´ onico es una tecla que causa que un elemento de men´ u pueda ser escogido por esta. Se puede usar el m´etodo setMnemonic() para dar una tecla de men´ u breve para cualquier elemento visible del men´ u. Por ejemplo, cuando se agrega la siguiente sentencia al constructor JFrameMenu2, en el c´ odigo 14, se permite usar una combinaci´on de teclas para acceder la opci´ on: menu1.setMnemonic(’A’); El nem´onico para el men´ u Archivo es puesta a A, as´ı la A en Archivo est´a subrayada. Cuando un usuario presiona Alt+A en el teclado, el resultado es el mismo si el usuario hubiera pulsado Archivo en el men´ u: la lista de men´ u es abierta y mostrada. Se deber´an usar diferentes nem´ onicos para cada elemento del men´ u que tengan una; si se usa el mismo nem´onico varias veces, s´ olo la primera asignaci´on trabaja. Generalmente, se usa la primera letra de la opci´ on. Si varios elementos del men´ u inician con la misma letra, la convenci´on es escoger la siguiente letra m´ as prominente en el nombre. Un acelerador es similar a un nem´ onico. Este es una combinaci´on de teclas que cause que un elemento del men´ u sea escogido si est´ a o no visible. Por ejemplo, varios programas permiten presionar CTRL+P para imprimir desde cualquier lugar en el programa. Solo elementos men´ u hoja— men´ us que no despliegan otros men´ us—pueden tener aceleradores. Por ejemplo, para asociar el acelerador CTRL+A para la opci´ on del men´ u “Marcar caja A”, se deber´a poner en el constructor de JFrameMenu2 del c´ odigo 14 lo siguiente: radio1.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_A, Event.CTRL_MASK)); Actividad 2. Crear una aplicaci´ on para una empresa de eventos sociales la cual usa una barra de men´ us con opciones m´ ultples, y que usa varios JPanel separados con diferentes manejadores de dise˜ no para organizar los componentes.

33