Está en la página 1de 119

Interfaces Gr acas de Usuario con JAVA

H ector Tejeda V Febrero, 2010

Indice general
1. Introducci on 1.1. Componentes, dise nadores y eventos . . . . . . . . . . . . . . 1.2. AWT y Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. Caso de estudio 2.1. Mostrando texto en un cuadro de di alogo 2.2. Ingresando texto en un cuadro de di alogo 2.2.1. Ejercicios . . . . . . . . . . . . . 2.3. Creando dibujos simples . . . . . . . . . 2.3.1. Ejercicios . . . . . . . . . . . . . 2.4. Dibujando rect angulos y elipses . . . . . 2.4.1. Ejercicios . . . . . . . . . . . . . 2.5. Figuras Rellenas y Colores . . . . . . . . 2.5.1. Ejercicios . . . . . . . . . . . . . 2.6. Dibujo de Arcos . . . . . . . . . . . . . . 2.6.1. Ejercicios . . . . . . . . . . . . . 2.7. Usando objetos con gr acas . . . . . . . 2.7.1. Ejercicios . . . . . . . . . . . . . 2.8. Texto e im agenes con etiquetas . . . . . 2.8.1. Ejercicio . . . . . . . . . . . . . . 2.9. Dibujado con polimorsmo . . . . . . . . 2.9.1. Ejercicios . . . . . . . . . . . . . 3. Componentes GUI 3.1. Introducci on . . . . . . . . . . . . . . . . 3.2. Generalidades de Componentes Swing . . 3.3. Mostrar texto e im agenes en una ventana 3.4. Campos de texto y eventos . . . . . . . . 5 6 7 9 9 10 11 12 15 16 18 19 21 22 24 25 28 30 32 32 32 35 35 35 38 42

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

4 3.5. 3.6. 3.7. 3.8. Tipos de eventos e interfaces receptoras . . Como trabaja el manejador de eventos . . JButton . . . . . . . . . . . . . . . . . . . Botones que mantienen estado . . . . . . . 3.8.1. JCheckBox . . . . . . . . . . . . . 3.8.2. JRadioButton . . . . . . . . . . . . 3.9. JComboBox . . . . . . . . . . . . . . . . . 3.10. JList . . . . . . . . . . . . . . . . . . . . . 3.11. Listas de selecci on m ultiple . . . . . . . . 3.12. Manejo de eventos del rat on . . . . . . . . 3.13. Clases adaptadoras . . . . . . . . . . . . . 3.14. Subclase JPanel para dibujar con el rat on 3.15. Manejo de eventos del teclado . . . . . . . 3.16. Manejadores de dise no . . . . . . . . . . . 3.16.1. FlowLayout . . . . . . . . . . . . . 3.16.2. BorderLayout . . . . . . . . . . . . 3.16.3. GridLayout . . . . . . . . . . . . . 3.17. Paneles anidados . . . . . . . . . . . . . . 3.18. JTextArea . . . . . . . . . . . . . . . . . . 3.19. Ejercicios . . . . . . . . . . . . . . . . . . 3.20. Usando Men us con Frames . . . . . . . . . 3.21. JPopupMenu . . . . . . . . . . . . . . . . 3.22. JTabbedPane . . . . . . . . . . . . . . . . 3.23. Manejador de Dise no: BoxLayout . . . . .

INDICE GENERAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 51 53 56 57 60 64 66 68 71 75 78 82 85 87 90 93 95 97 99 100 108 112 114

Cap tulo 1 Introducci on


Se presenta en este material, ejemplos que no son considerados en un curso introductorio de Java, ya que las aplicaciones que se revisan tienen interfaces de usuario que utilizan exclusivamente texto. La raz on por la cual son usadas estas interfaces textuales no es, porque tengan una gran ventaja; en realidad, la u nica ventaja que tienen es su facilidad para ser creadas. Por lo general, en un curso introductorio de Java se pretende no distraer mucho la atenci on del estudiante en las cuestiones importantes del desarrollo de software; por lo que en general la mayor a de los cursos introductorios se centran en cuestiones relacionadas con la estructura y la interacci on de los objetos, el dise no de clases y la calidad del c odigo. Las interfaces gr acas de usuario o GUI (Graphical User Interface ) son tambi en construidas usando objetos que interact uan, pero cuentan con una estructura muy especializada y es por lo anterior que se evita usarlas antes de aprender la estructura de los objetos en t erminos m as generales. Una vez que se tienen las bases, se est a preparado para dar una mirada a la construcci on de las GUI. Las GUI completan las aplicaciones con una interfaz formada por ventanas, men us, botones y otros componentes gr acos, y hacen que la aplicaci on tenga una apariencia m as parecida a las aplicaciones t picas, que son usadas por la mayor a de la gente que usa un sistema de c omputo. Se debe observar el doble signicado de la palabra interfaz. Las interfaces de las que se abordan en este material no son las interfaces de las clases ni la construcci on interfaz de Java. Cuando se dice interfaces de usuario, se reere a la parte de una aplicaci on que est a visible en la pantalla y que permite que un usuario interact ue con ella.

Introducci on

Una vez que se sabe c omo crear una GUI en Java, se pueden desarrollar programas que tengan una mejor presentaci on visual.

1.1.

Componentes, gestores de disposici on y captura de eventos

Para la creaci on de una GUI son varios los detalles que est an involucrados. En este material no se cubren todos los detalles de las distintas tareas que se pueden hacer, s olo se discuten los principios generales y un buen n umero de ejemplos. En Java, toda la programaci on de una GUI se hace mediante el uso de bibliotecas de clases est andares especializadas. Una vez que se han comprendido los principios se pueden encontrar todos los detalles necesarios en la documentaci on de la biblioteca est andar. Los principios que se necesitan revisar se pueden dividir en tres bloques: 1. Las clases de elementos que se pueden mostrar en la pantalla. 2. La forma como se pueden acomodar los elementos que se muestran en la pantalla. 3. La forma como se debe responder a una entrada del usuario. Se discuten los puntos anteriores mediante los t erminos componentes, gestores de dispositivos y manejo de eventos respectivamente. Los componentes son las partes individuales con las cuales se construye una GUI. Ejemplos de estos son los botones, los men us, los elementos del men u, las cajas de vericaci on, los deslizadores, los campos de texto, etc. La biblioteca de Java contiene una cantidad de componentes dise nados para ser usados inmediatamente y tambi en es posible que el programador escriba sus propios componentes. Es necesario que se aprenda cu ales son los componentes importantes, c omo son creados y c omo hacer para que aparezcan en la pantalla tal cual se desea verlos. Los gestores de disposici on son empleados en la ubicaci on de los componentes en la pantalla. Los sistemas de GUI m as viejos y primitivos manejaban coordenadas bidimensionales, donde el programador indicaba mediante un par ordenado de valores, que expresaban un valor en p xeles, la posici on del componente adem as del alto y el ancho del mismo. En los sistemas de GUI

1.2 AWT y Swing

m as modernos, esta forma es muy simple, ya que se debe tener en cuenta las distintas resoluciones de pantalla, las diferentes fuentes, las ventanas que los usuarios pueden redimensionar, y otros aspectos que hacen dif cil la distribuci on de los componentes. La soluci on es un esquema donde el programador pueda indicar la disposici on de los componentes en t erminos m as generales. Por ejemplo, se puede indicar que este componente deber a estar debajo de este otro o que este componente se estrechar a cuando la ventana cambie de tama no pero este otro tendr a un tama no constante. Lo anterior se logra usando los gestores de disposici on. El manejo de eventos se reere a la t ecnica que se usa para responder a las entradas del usuario. Una vez que los componentes han sido creado y que han sido posicionados en la pantalla, es necesario asegurar de que ocurra algo cuando el usuario presione un bot on, por ejemplo. El modelo que usa la biblioteca de Java para lograr lo anterior est a basada en eventos: si un usuario activa un componente, por ejemplo, por pulsar un bot on o seleccionar un elemento de un men u, el sistema generar a un evento. Entonces, la aplicaci on puede recibir una noticaci on del evento, mediante la invocaci on de uno de sus m etodos, y se puede llevar a cabo la acci on adecuada.

1.2.

AWT y Swing

Java tiene dos bibliotecas para la construcci on de interfaces gr acas de usuario. La m as antigua, denominada AWT (Abstract Window Toolkit ), fue introducida con el primer sistema Java original; m as tarde, se agreg o una mejor biblioteca denominada Swing. Swing utiliza algunas de las clases de la biblioteca AWT, reemplaza algunas de las clases de AWT con sus propias versiones y agrega clases nuevas. En este material, se usar a la biblioteca Swing, aunque se usar an algunas de las clases de AWT que todav a son empleadas en los programas Swing. Para el caso de que existan clases equivalentes en ambas bibliotecas, se usar an las versiones de Swing. Como existen clases equivalentes en AWT y en Swing, las versiones Swing han sido identicadas mediante el agregado de la letra ((J)) al comienzo del nombre de la clase. Por ejemplo, existen las clases de nombre Button y JButton, Frame y JFrame, Menu y JMenu, etc. Las clases que comienzan con ((J)) son versiones Swing; y ser an las u nicas que se usar an.

Introducci on

Cap tulo 2 Caso de estudio


Este caso de estudio est a dise nado para iniciar el aprendizaje de las potentes capacidades de Java para crear GUIs. Se muestran diez secciones breves, en donde cada secci on introduce unos cuantos conceptos b asicos y proporciona ejemplos visuales gr acos. En las secciones subsecuentes, se emplean conceptos de la programaci on orientada a objetos para crear aplicaciones que dibujan una variedad de guras.

2.1.

Mostrando texto en un cuadro de di alogo

Muchas aplicaciones usan ventanas o cuadros de di alogo, tambi en llamados di alogos para mostrar la salida. Por ejemplo, los navegadores como Firefox o Microsoft Internet Explorer muestran p aginas web en su propia ventana. Programas de correo electr onico permiten teclear y leer mensajes en una ventana. T picamente, los cuadros de di alogo son ventanas en las cuales los programas muestran mensajes importantes a los usuarios. La clase JOptionPane proporciona cuadros de di alogo empaquetados previamente que permiten a los programas mostrar ventanas conteniendo ventanas tales ventanas son llamadas di alogos de mensaje. El c odigo que se muestra a continuaci on muestra la cadena Bienvenido a Java en tres renglones.
1 // Dialogo1.java 2 // Imprimiendo m ultiples l neas en un cuadro de di alogo 3 import javax.swing.JOptionPane; // importar la clase JOptionPane 4

10

Caso de estudio

5 public class Dialogo1 { 6 public static void main( String args[] ) { 7 // Mostrar un cuadro de di alogo con un mensaje 8 JOptionPane.showMessageDialog( null, "Bienvenido\na\nJava" ); 9 } // fin del main 10 } // fin del cuadro de di alogo

En la l nea 3 se indica que el programa usar a la clase JOptionPane del paquete javax.swing. Este paquete contiene varias clases que ayudan a crear la GUI para las aplicaciones. Los componentes GUI facilitan la entrada de datos para un usuario, y la presentaci on de datos al usuario. La l nea 8 llama al m et odo showMessageDialog para mostrar un cuadro de di alogo conteniendo un mensaje. El m etodo requiere dos argumentos. El primer argumento determina el Frame al cual es asociado el di alogo, si es null se asocia con el Frame por defecto. El segundo argumento es el String que ser a mostrado en el di alogo. El m etodo showMessageDialog es un m etodo est atico de la clase JOptionPane. Los m etodos est aticos denen frecuentemente tareas usadas que no requieren la creaci on expl cita de un objeto. Por ejemplo, muchos programas muestran cuadros de di alogo, y en vez de requerir que se cree c odigo que haga la tarea, los dise nadores de la clase JOptionPane declararon un m etodo est atico que realiza la tarea del programador. Un m etodo est atico generalmente es llamado usando el nombre de la clase seguido por un punto y el nombre del m etodo.

2.2.

Ingresando texto en un cuadro de di alogo

La aplicaci on que se muestra enseguida usa otro cuadro de di alogo predenido JOptionPane llamado di alogo de entrada, que permite al usuario ingresar datos en el programa. El programa pide el nombre del usuario, y responde con un cuadro de mensaje conteniendo un saludo y el nombre que el usuario haya ingresado.
1 2 3 4 5 // NombreDialogo.java // Entrada B asica con un cuadro de di alogo. import javax.swing.JOptionPane; public class NombreDialogo {

2.2 Ingresando texto en un cuadro de di alogo

11

6 7 public static void main( String args[] ) { 8 // solicitar al usuario que ingrese un nombre 9 String nombre = 10 JOptionPane.showInputDialog( "Cu al es tu nombre?" ); 11 // crear el mensaje 12 String mensaje = String.format( 13 "Bienvenido, %s, a la Programaci on con Java!", nombre ); 14 // mostrar el mensaje de bienvenida al usuario 15 JOptionPane.showMessageDialog( null, mensaje ); 16 } // fin de main 17 } // fin de la clase NombreDialogo

Las l neas 910 usan el m etodo showInputDialog de JOptionPane para mostrar un di alogo de entrada conteniendo un mensaje y un campo, conocido como campo de texto, en el cual el usuario puede poner texto. El argumento pasado al m etodo es el mensaje que indica lo que el usuario deber a ingresar. El usuario teclea car acteres en el campo de texto, y despu es pulsa el bot on Aceptar o tambi en puede presionar la tecla Intro para mandar la cadena al programa. El m etodo showInputDialog devuelve un String conteniendo los car acteres tecleados por el usuario. La cadena es almacenada en la variable nombre. Si se presiona el bot on Cancelar en el di alogo, el m etodo regresa null y el programa muestra la palabra null como el nombre. Las l neas 1213 usan el m etodo est atico format que devuelve un String para regresar una cadena conteniendo el saludo con el nombre del usuario. El m etodo format es parecido al m etodo System.out.printf, excepto que format regresa la cadena formateada en vez de mostrarla. La l nea 14 muestra el saludo en un mensaje de di alogo.

2.2.1.

Ejercicios

1. Escribir un programa que use entradas y salidas con cuadros de di alogo con los m etodos de la clase JOptionPane para multiplicar dos n umeros. Como el m etodo showInputDialog regrese un String, se deber a convertir el String ingresado por el usuario a un tipo int para hacer el c alculo. El m etodo Integer.parseInt( String s ) toma un argumento tipo String representando un entero y regresa el valor como un tipo int. El m etodo parseInt es un m etodo est atico de

12 la clase Integer del paquete java.lang.

Caso de estudio

2.3.

Creando dibujos simples

Una de las caracter sticas de Java es el soporte de gr acos que permite a los programadores visualmente resaltar sus aplicaciones. En esta secci on se muestra una de las capacidades gr acas de Java dibujado de l neas. Tambi en se cubre lo b asico para la creaci on de una ventana para mostrar un dibujo sobre la pantalla de la computadora. Para dibujar en Java, se requiere entender el sistema de coordenadas, un esquema para identicar cada punto en la pantalla. Por defecto, la esquina superior izquierda de un componente GUI tiene coordenadas (0,0). Una par coordenado est a compuesto de un coordenada en x, en este caso la coordenada horizontal, y una coordena en y , la coordenada vertical. La coordenada en x es la localidad horizontal movi endose de izquierda a derecha. La coordenada en y es la localidad vertical movi endose de arriba hacia abajo. Las coordenadas indican donde el gr aco deber a ser mostrado en pantalla. Las unidades de las coordenadas est an medidas en p xeles. Un pixel es la unidad m as peque na de resoluci on que despliega el monitor. El t ermino pixel viene de las palabras del ingl es picture element. La aplicaci on que se muestra a continuaci on s olo dibuja dos l neas. La clase DibujaPanel realiza el dibujo actual, mientras la clase DibujaPanelPrueba crea una ventana para mostrar el dibujo. En la clase DibujaPanel, las sentencias import en las l neas 45 permiten usar la clase Graphics del paquete java.awt, el cual proporciona varios m etodos para dibujar texto y guras sobre la pantalla, y la clase JPanel del paquete javax.swing proporciona una area sobre la cual se puede dibujar.
1 2 3 4 5 6 7 8 9 10 11 // Clase DibujaPanel.java // Usando drawLine para conectar las esquinas de un panel. import java.awt.Graphics; import javax.swing.JPanel; public class DibujaPanel extends JPanel { // dibujar una X desde las esquinas del panel public void paintComponent( Graphics g ) {

2.3 Creando dibujos simples


12 // llamar a paintComponent para asegurar que el panel 13 // se muestra correctamente 14 super.paintComponent( g ); 15 int ancho = getWidth(); // ancho total 16 int alto = getHeight(); // altura total 17 18 // dibujar una l nea desde la izquierda superior 19 // hasta la derecha inferior 20 g.drawLine( 0, 0, ancho, alto ); 21 22 // dibujar una l nea desde la izquierda inferior 23 // hasta la derecha superior 24 g.drawLine( 0, alto, ancho, 0 ); 25 } // fin del m etodo paintComponent 26 } // fin de la clase DibujaPanel

13

En la l nea 7 se usa la palabra reservada extends para indicar que la clase DibujaPanel es una mejora del tipo JPanel. Con extends se indica una relaci on de herencia en la cual la clase DibujaPanel inicia con los miembros existentes (datos y m etodos) de la clase JPanel. La clase desde la cual DibujaPanel hereda, JPanel, aparece a la derecha de la palabra extends. En esta relaci on de herencia, JPanel es llamada la superclase y DibujaPanel es llamada la subclase. Con lo anterior se obtiene que la clase DibujaPanel tenga los atributos (datos) y comportamiento (m etodos) de la clase JPanel y adem as las nuevas caracter sticas que se agregan en la declaraci on de la clase DibujaPanel espec camente, la habilidad para dibujar dos l neas a lo largo de las diagonales del panel. Cada JPanel, incluyendo DibujaPanel, tienen un m etodo paintComponent, l neas 1025, el cual es llamado por el sistema autom aticamente cada vez que se necesita mostrar el JPanel. Este m etodo deber a ser sobreescrito si se desea dibujar algo en el panel. Este m etodo es llamado cuando un JPanel es mostrado por primera vez en la pantalla, cuando este es cubierto y despu es descubierto por alguna ventana, y cuando la ventana es redimensionada. Este m etodo requiere un argumento, un objeto Graphics, que es proporcionado por el sistema cuando se llama a paintComponent. La primera sentencia en cada m etodo paintComponent que sobreescriba al m etodo heredado deber a ser super.paintComponent( g ); lo cual asegura que el panel es dibujado apropiadamente en la pantalla antes de iniciar el dibujo. En las l neas 15 y 16 se llaman dos m etodos que la

14

Caso de estudio

clase DibujaPanel hereda de la clase JPanel, en general, cualquier clase que extienda a otra, podr a usar cualquier m etodo que est e declarado en la superclase que tenga al modicador public. Los m etodos getWidth y getHeight regresan el ancho y el alto del JPanel respectivamente, los cuales son almacenados en las variables que est an declaradas en las l neas 15 y 16. En las l neas 20 y 24 se usa la referencia g del tipo Graphics para llamar al m etodo drawLine que dibujar a las l neas. Los primeros dos argumentos, del m etodo drawLine, son las coordenadas de un extremo de la l nea, y los otros dos son las coordenadas del otro extremo. Si se redimensiona la ventana las l neas ser an escaladas autom aticamente, ya que los argumentos est an basados en el ancho y alto del panel. Redimensionando la ventana en esta aplicaci on provoca que el sistema llame al m etodo paintComponent para redibujar el contenido de DibujaPanel. Para mostrar DibujaPanel en la pantalla, se deber a colocar este dentro de una ventana. Se puede crear una ventana con un objeto de la clase JFrame. En DibujaPanelPrueba, que se muestra enseguida, la l nea 4 se importa la clase JFrame del paquete javax.swing. En la l nea 11 en el m etodo main de la clase DibujaPanelPrueba se crea una instancia de la clase DibujaPanel, la cual contendr a el dibujo, y la l nea 14 crea un nuevo JFrame que puede contener y mostrar el panel. La l nea 17 llama al m etodo setDefaultCloseOperation on decon el argumento JFrame.EXIT ON CLOSE para indicar que la aplicaci ber a terminar cuando el usuario cierre la ventana. La l nea 17 usa el m etodo add de la clase JFrame para poner el panel conteniendo el dibujo en el frame. La l nea 19 pone el tama no del frame, empleando el m etodo size d andole dos par ametros el ancho del frame, y el alto. En la l nea 20 se muestra el JFrame.
1 2 3 4 5 6 7 8 9 10 11 12 13 // DibujaPanelPrueba.java // Aplicaci on para montar un DibujaPanel. import javax.swing.JFrame; public class DibujaPanelPrueba { public static void main( String args[] ) { // crear un panel que contenga el dibujo DibujaPanel panel = new DibujaPanel(); // crear un nuevo frame para contener al panel

2.3 Creando dibujos simples


14 JFrame aplicacion = new JFrame(); 15 16 // indicar que al salir del frame se cierre la aplicaci on 17 aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 18 aplicacion.add( panel ); // agregar el panel al frame 19 aplicacion.setSize( 250, 250 ); // fijar el tama~ no del frame 20 aplicacion.setVisible( true ); // hacer visible el frame 21 } // fin de main 22 } // fin de la clase DibujaPanelPrueba

15

2.3.1.

Ejercicios

1. Usando ciclos y sentencias de control dibujar l neas para obtener dise nos interesantes. a ) Crear un dise no que dibuje l neas desde la esquina superior izquierda, despleg andose en abanico hasta que cubran la mitad superior izquierda del panel. Una aproximaci on es dividir el ancho y alto en un n umero igual de pedazos (15 pedazos estar a bien). El primer extremo de una l nea siempre estar a en la esquina superior izquierda (0,0), El segundo extremo puede encontrarse iniciando en la esquina inferior izquierda, luego moverse hacia arriba un pedazo vertical y un pedazo horizontal a la derecha. Dibujar una l nea entre los dos extremos. Continuarse moviendo el extremo, arriba y a la derecha, hasta llegar a la esquina superior derecha. La gura se deber a ajustar cuando se redimensione la ventana. b ) Modiciar el programa del ejercicio anterior para desplegar l neas desde las cuatro esquinas. Las l neas de las esquinas opuestas se deber an intersectar. 2. Realizar los siguientes programas. a ) Crear un dise no iniciando con la divisi on de cada lado del panel en la misma cantidad de partes, se puede escoger 15. La primera l nea inicia en la esquina superior izquierda y termina una parte a la derecha sobre el lado inferior. Para las siguientes l neas, se deber a mover hacia abajo en una parte del lado izquierdo, y una parte hacia la derecha en el lado inferior. Repetir lo anterior hasta que se alcance en el lado inferior la esquina inferior derecha.

16

Caso de estudio b ) Modicar el programa del ejercicio anterior para espejear el dise no en las cuatro esquinas.

2.4.

Dibujando rect angulos y elipses

En esta secci on se muestra como dibujar rect angulos y elipses, usando de la clase Graphics los m etodos drawRect y drawOval respectivamente.
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 // Figuras.java // Se muestran diferentes figuras que pueden ser dibujadas import java.awt.Graphics; import javax.swing.JPanel; public class Figuras extends JPanel { private int opcion; // opci on del usuario de la figura a dibujar // El constructor pone la opci on del usuario public Figuras( int opcionUsuario ) { opcion = opcionUsuario; } // fin del constructor Figuras // dibujar una cascada de figuras iniciando desde la esquina // superior izquierda public void paintComponent( Graphics g ) { super.paintComponent( g ); for ( int i = 0; i < 10; i++ ) { // selecionar la figura basandose en la opci on del usuario switch ( opcion ) { case 1: // dibujar rect angulos pasando las coordenadas del // rect angulo dado por la esquina x, y, con ancho y alt g.drawRect( 10 + i * 10, 10 + i * 10, 50 + i * 10, 50 + i * 10 ); break; case 2: // dibujar elipses g.drawOval( 10 + i * 10, 10 + i * 10, 50 + i * 10, 50 + i * 10 ); break; } // fin del switch } // fin del for } // fin del m etodo paintComponent } // fin de la clase Figuras

La l nea 6 inicia con la declaraci on de la clase Figuras, la cual extiende a la clase JPanel. La variable de instancia, opcion, declarada en la l nea 7,

2.4 Dibujando rect angulos y elipses

17

determina si el m etodo paintComponent deber a dibujar rect angulos o elipses. El constructor en las l neas 1012 inicializa opci on con el valor pasado en el par ametro opcionUsuario. El m etodo paintComponent, de las l neas 1632, hace el dibujo. No se debe olvidar que la primera sentencia que deber a ser llamada en este m etodo es super.paintComponent, como aparece en la l nea 19. Entre las l neas 18 31 se tiene un ciclo que dibuja 10 guras. La sentencia switch, l neas 2030, selecciona entre dibujar rect angulos y elipses. Si opcion tiene 1, entonces el programa dibuja un rect angulo, mediante la llamada al m etodo drawRect de la clase Graphics en las l neas 2324. Este m etodo requiere cuatro argumentos, siendo los dos primeros las coordenadas de la esquina superior izquierda del rect angulo, y los siguientes dos par ametros representan el ancho y el alto del rect angulo. En este ejemplo se inicia en una posici on 10 p xeles abajo y 10 p xeles a la derecha de la esquina superior izquierda, y en cada iteraci on del ciclo se mueve la esquina superior izquierda otros 10 p xeles hacia abajo y a la derecha. El ancho y la altura del rect angulo inician en 50 p xeles y se incrementan en 10 p xeles en cada iteraci on. Si opcion tiene 2, el programa dibuja una elipse. Cuando se dibuja una elipse, se encuentra contenida en un rect angulo, bounding rectangle, y la elipse toca los cuatro puntos medios del rect angulo. El m etodo drawOval, l neas 2728, requiere los mismos cuatro argumentos que el m etodo drawRect. Los argumentos especican la posici on y el tama no del rect angulo que acota a la elipse. Para este caso son los mismos valores que fueron dados para el rect angulo. Se muestra enseguida el programa que es el responsable para manejar la entrada del usuario y crear una ventana para desplegar los dibujos apropiados usando la selecci on del usuario.
1 2 3 4 5 6 7 8 9 10 11 // ProbarFiguras.java // Aplicaci on de prueba que muestra la clase Figuras import javax.swing.JFrame; import javax.swing.JOptionPane; public class ProbarFiguras { public static void main( String args[] ) { // obtener la opci on del usuario String entrada = JOptionPane.showInputDialog(

18

Caso de estudio

12 "Ingresar 1 para dibujar rect angulos\n" + 13 "Ingresar 2 para dibujar ovalos" ); 14 // convertir la entrada a int 15 int opcion = Integer.parseInt( entrada ); 16 // crear el panel con la entrada del usuario 17 Figuras panel = new Figuras( opcion ); 18 JFrame application = new JFrame(); // crear a nuevo JFrame 19 application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 20 application.add( panel ); // agregar el panel al frame 21 application.setSize( 300, 300 ); // fijar el tama~ no deseado 22 application.setVisible( true ); // mostrar el frame 23 } // fin de main 24 } // fin de la clase ProbarFiguras

En las l neas 1113 se pide al usuario, con un cuadro de di alogo de entrada, que seleccione el tipo de guras a dibujar; la respuesta es almacenada en la variable entrada. En la l nea 15 se emplea el m etodo parseInt de la clase Integer para convertir el String guardado en la variable entrada a un tipo int y se asigna a la variable opcion. Una instancia de la clase Figuras es creada en la l nea 17, pasando la opci on del usuario al constructor. Las l neas 1722 realizan las operaciones habituales para crear y congurar la ventana crear un frame, congurar salir cuando la aplicaci on sea cerrada, agregar el dibujo al frame, congurar el tama no del frame y hacerlo visible.

2.4.1.

Ejercicios

1. Dibujar 12 c rculos conc entricos en el centro de un JPanel. El c rculo m as interno deber a tener un radio de 10 p xeles, y cada c rculo sucesivo deber a tener un radio de 10 p xeles m as grande que el previo anterior. Iniciar encontrando el centro del JPanel. Para obtener la esquina superior izquierda de un c rculo moverse un radio hacia arriba y un radio hacia la izquierda desde el centro. El ancho y el alto del rect angulo acotador es el di ametro del c rculo (dos veces el radio). 2. Crear un programa que lea la entrada de varios valores, usando cuadros de di alogo, para mostrar una gr aca de barras con rect angulos, de acuerdo a los valores dados.

2.5 Figuras Rellenas y Colores

19

2.5.

Figuras Rellenas y Colores

Se pueden crear muchos dise nos interesantes con s olo l neas y guras b asicas, la clase Graphics proporciona muchas m as capacidades. Se revisar an a continuaci on las caracter sticas de colores y guras rellenas. Agregando color se agrega otra caracter stica a los dibujos que el usuario ve en la computadora. Las guras rellenas cubren totalmente regiones con colores s olidos, en vez de s olo dibujar los contornos. Los colores mostrados en las pantallas de las computadoras est an denidos por sus partes de rojo, verde y azul. Estas partes, conocidos como valores RGB (Red Green Blue), tiene valores enteros entre 0 y 255. Entre m as grande sea el valor, mayor tinte tendr a el color nal. Java emplea la clase Color del paquete java.awt para representar colores usando sus valores RGB. La clase Color en el paquete java.awt es empleada por Java para representar colores usando los valores RGB. La clase Color contiene 13 objetos predenidos est aticos Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK GRAY, Color.GRAY, Color.GREEN, Color.LIGHT GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE y Color.YELLOW. La clase Color tambi en contiene un constructor de la forma: public Color( int r, int g, int b) para que se puedan crear colores hechos a la medida especicando los componentes individuales rojo, verde y azul de un color. Los rect angulos y las elipses rellenas son dibujados con los m etodos fillRect y fillOval de la clase Graphics, respectivamente. Estos dos m etodos tienen los mismos par ametros como sus contrapartes sin rillenar drawRect y drawOval; los primeros dos par ametros son las coordenadas para la esquina superior izquierda de la gura, mientras los siguientes dos par ametros determinan su ancho y alto. El c odigo de enseguida crea una cara sonriente, ver gura 2.1, empleando colores y guras rellenas.
1 2 3 4 5 6 7 8 // CaraSonriente.java // Muestra figuras rellenas import java.awt.Color; import java.awt.Graphics; import javax.swing.JPanel; class CaraSonriente extends JPanel {

20

Caso de estudio

Figura 2.1: Una cara sonriente empleando fillOval y la clase java.awt.Color


9 10 public void paintComponent( Graphics g ) { 11 super.paintComponent( g ); 12 // dibujar la cara 13 g.setColor( Color.YELLOW ); 14 g.fillOval( 10, 10, 200, 200 ); 15 // draw los ojos 16 g.setColor( Color.BLACK ); 17 g.fillOval( 55, 65, 30, 30 ); 18 g.fillOval( 135, 65, 30, 30 ); 19 // dibujar la boca 20 g.fillOval( 50, 110, 120, 60 ); 21 // "retocar" la boca en una sonrisa 22 g.setColor( Color.YELLOW ); 23 g.fillRect( 50, 110, 120, 30 ); 24 g.fillOval( 50, 120, 120, 40 ); 25 } // fin del m etodo paintComponent 26 } // fin de CaraSonriente

Las sentencias import en las l neas 46 del c odigo anterior importan las clases Color, Graphics y JPanel. La clase CaraSonriente, l neas 1025, usa la clase Color para especicar los colores de dibujo, y usa la clase Graphics para dibujar. La clase JPanel proporciona el a rea en la cual se dibujar a. En la l nea 13 se emplea setColor de la clase Graphics para indicar el color con el que se dibujar a usando el color amarillo. El m etodo setColor requiere un argumento, el color que ser a puesto como el color para dibujar. La l nea 14 dibuja un c rculo con di ametro 200 para representar la cara. En la l nea 16 se pone el color negro, y las l neas 17 y 18 ponen los ojos. La boca se dibuja con una elipse en la l nea 20, pero no tiene el dise no requerido. Para

2.5 Figuras Rellenas y Colores

21

formar la sonrisa en la boca, se retoca la boca. En la l nea 22 se pone el color amarillo y en la l nea 23 se dibuja un rect angulo que tiene la mitad de altura de la boca, con lo que se borra la mitad superior de la boca, quedando solo la mitad inferior visible. Para crear una mejor sonrisa la l nea 24 dibuja otra elipse para cubrir ligeramente la parte superior de la boca.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // PruebaCaraSonriente // Probar aplicaci on que muestra cara sonriente import javax.swing.JFrame; public class PruebaCaraSonriente { public static void main( String args[] ) { CaraSonriente panel = new CaraSonriente(); JFrame aplicacion = new JFrame(); aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); aplicacion.add( panel ); aplicacion.setSize( 230, 250 ); aplicacion.setVisible( true ); } // fin de main } // fin de la clase PruebaCaraSonriente

La clase PruebaCaraSonriente, c odigo de arriba, crea y muestra un JFrame conteniendo el dibujo. Cuando el JFrame es mostrado, el sistema llama al m etodo paintComponent para dibujar la cara sonriente.

2.5.1.

Ejercicios

1. Usando el m etodo fillOval, dibujar una diana que alterne entre dos colores aleatorios. Usar el constructor Color( int r, int g, int b) con argumentos aleatorios para generar colores aleatorios. 2. Crear un programa que dibuje 10 guras rellenas aleatorias en colores, posiciones y tama nos aleatorios. El m etodo paintComponent deber a contener un ciclo que itere 10 veces. En cada iteraci on, el ciclo deber a determinar si dibuja un rect angulo relleno o una elipse, crear un color aleatorio y escoger coordenadas y dimensiones aleatorias. Las coordenadas deber an escogerse basadas en el ancho y alto del panel. Longitudes de los lados deber an limitarse a la mitad del ancho y alto de la ventana.

22

Caso de estudio

2.6.

Dibujo de Arcos

Usando las caracter sticas gr acas de Java, se pueden crear dibujos m as complejos que ser an m as tediosos codicar l nea por l nea. En el siguiente c odigo se emplean arreglos y sentencias de repetici on para dibujar un arco iris, ver gura 2.2, usando el m etodo fillArc de la clase Graphics. El dibujado de arcos es similar al dibujado de elipses un arco es simplemente una secci on de una elipse.

Figura 2.2: Dibujo de un arco iris empleando drawArc

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

// DibujaArcorIris.java // Se muestra el uso de colores en un arreglo. import java.awt.Color; import java.awt.Graphics; import javax.swing.JPanel; class DibujaArcoIris extends JPanel { // Definir el color ndigo y violeta final Color VIOLETA = new Color( 128, 0, 128 ); final Color INDIGO = new Color( 75, 0, 130 ); // Colores para el arco iris, iniciando con el mas interno. // Las dos entradas en blanco dan un arco vac o en el centro private Color colores[] = { Color.WHITE, Color.WHITE, VIOLETA, INDIGO, Color.BLUE, Color.GREEN, Color.YELLOW, Color.ORANGE, Color.RED }; // constructor public DibujaArcoIris() {

2.6 Dibujo de Arcos


22 setBackground( Color.WHITE ); // fijar el fondo a blanco 23 } // fin del constructor DibujaArcoIris 24 25 // dibujar un arco iris usando c rculos conc entricos 26 public void paintComponent( Graphics g ) { 27 super.paintComponent( g ); 28 29 int radio = 20; // radio de un arco 30 31 // dibujar el arco iris en la parte inferior y al centro 32 int centroX = getWidth() / 2; 33 int centroY = getHeight() - 10; 34 35 // dibujar arcos rellenos iniciando con el m as exterior 36 for ( int i = colores.length; i > 0; i-- ) { 37 // fijar el color para el arco actual 38 g.setColor( colores[ i - 1 ] ); 39 40 // fijar el arco desde 0 a 180 grados 41 g.fillArc( centroX - i * radio, centroY - i * radio, 42 i * radio * 2, i * radio * 2, 0, 180 ); 43 } // fin del for 44 } // fin del m etodo paintComponent 45 } // fin de la clase DibujaArcoIris

23

El c odigo anterior inicia con las sentencias import usuales para crear los d bujos, l neas 35. Las l neas 1011 declaran y crean dos nuevos colores VIOLETA e INDIGO. Para los colores del arco iris en la clase Color se encuentran denidos los primeros 5 de los 7 colores del arco iris. En las l neas 1517 se inicializa un arreglo con los colores del arco iris, iniciando primero con los arcos m as internos. El arreglo inicia con dos elementos Color.WHITE, los cuales son para dibujar los arcos vac os en el centro del arco iris. El constructor de las l neas 2123 contiene una sola sentencia que llama al m etodo setBackground, el cual se hereda desde la clase JPanel, con el par ametro Color.White. El m etodo setBackground toma un solo argumento tipo Color y ja el fondo del componente a ese color. En la l nea 29 se declara la variable local radio, la cual determina el radio de cada arco. Las variables locales centroX y centroY, l neas 3233, determinan la localidad del punto medio en la base de la ventana. El ciclo en las l neas 3643 usa la variable de control i para contar hacia atr as a partir del nal del arreglo, dibujando los arcos m as grandes primero y colocando arcos m as peque nos sucesivante al frente del previo. En la l nea 38 se ja el

24

Caso de estudio

color para dibujar el arco actual desde el arreglo. El m etodo fillArc usado en las l neas 4142 dibuja un semic rculo lleno. Este m etodo requiere seis par ametros. Los primeros cuatro representan el rect angulo acotador en el cual el arco ser a dibujado. Los primeros dos de estos indican las coordenadas de la esquina superior izquierda del rect angulo acotador, y los siguientes dos indican el ancho y alto. El quinto par ametro es el angulo inicial en la elipse, y el sexto indica el barrido, o la cantidad de arco a cubrir. El angulo inicial y de barrido est an medidos en grados, con cero grados apuntando a la derecha. Un barrido positivo dibuja el arco en sentido contrario a las manecillas, mientras uno negativo dibuja en el sentido de las manecillas. Un m etodo similar a fillArc es drawArc este requiere los mismos par ametros como fillArc, pero dibuja la arista del arco en vez de llenarlo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // PruebaDibujaArcoIris.java // Aplicaci on de prueba para mostrar un arco iris. import javax.swing.JFrame; public class PruebaDibujaArcoIris { public static void main( String args[] ) { DibujaArcoIris panel = new DibujaArcoIris(); JFrame aplicacion = new JFrame(); aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); aplicacion.add( panel ); aplicacion.setSize( 400, 250 ); aplicacion.setVisible( true ); } // fin del main } // fin de la clase PruebaDibujaArcoIris

La clase PruebaDibujaArcoIris, c odigo anterior, crea y congura un JFrame para mostrar el arco iris. Una vez que el programa hace al panel visible, el sistema llama al m etodo paintComponent de la clase DibujaArcoIris para dibujar el arco iris en la pantalla.

2.6.1.

Ejercicios

1. En el ejercicio, se dibujar an espirales, ver gura 2.3, con los m etodos drawLine y drawArc. Las espirales deber an cubrir todo el panel, no debe haber zonas sin llenar al redimensionar la ventana.

2.7 Usando objetos con gr acas

25

a ) Dibujar una espiral cuadrada centrada en el panel, usando el m etodo drawLine. Una t ecnica es usar un ciclo que incremente la longitud de la l nea despu es de dibujar la segunda l nea. La direcci on para dibujar la siguiente linea deber a seguir un patr on, como abajo, izquierda, arriba, derecha. b ) Dibujar una espiral circular usando el m etodo drawArc para dibujar un semic rculo cada vez. Cada semic rculo sucesivo deber a tener un radio mayor y deber a continuar dibujando donde el semic rculo previo termino.

Figura 2.3: Dibujo de espirales usando drawLine y drawArc

2.7.

Usando objetos con gr acas

Los ejemplos que se han revisado hasta ahora no var an cada vez que se ejecuta el programa. Sin embargo, en el segundo ejercicio de la subsecci on 2.5.1 se pide crear un programa que genera guras y colores de manera aleatoria. En aquel ejercicio, el dibujo cambia cada vez que el sistema llama a paintComponent para redibujar la pantalla. Para crear un dibujo m as consistente que permanezca igual cada vez que es dibujado, se debe guardar la informaci on acerca de las guras mostradas para que se puedan reproducir de forma exacta cada vez que el sistema llame a paintComponent.

26

Caso de estudio

Para realizar lo anterior, se crear a un conjunto de clases de guras que guardar an informaci on acerca de cada gura. Se har an estas clases inteligentes permitiendo que objetos de estas clases dibujarse a si mismo si se proporciona un objeto Graphics. En el c odigo que aparace enseguida, la clase MiLinea tiene todas las capacidades indicadas. La clase MiLinea importa las clases Color y Graphics en las l neas 34. Las l neas 812 declaran variables de instancia para las coordenadas necesarias para dibujar una l nea, y la l nea 12 declara la variable de instancia que guarda el color de la l nea. El constructor en las l neas 1521 toma cinco par ametros, uno para cada variable de instancia que se inicializar a. El m etodo dibujar en las l neas 2427 necesita un objeto Graphics que es usado para dibujar la l nea en el color y las coordenadas apropiadas.
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 // MiLinea.java // Declaraci on de la clase MiLinea import java.awt.Color; import java.awt.Graphics; public class MiLinea { private private private private private int x1; // coordenada en x int y1; // coordenada en y int x2; // coordenada en x int y2; // coordenada en y Color miColor; // color de del primer extremo del primer extremo del segundo extremo del segundo extremo esta figura

// constructor con valores de entradas public MiLinea( int x1, int y1, int x2, this.x1 = x1; // poner el valor en x this.y1 = y1; // poner el valor en y this.x2 = x2; // poner el valor en x this.y2 = y2; // poner el valor en y miColor = color; // poner el color } // fin del constructor MiLinea // Dibujar la l nea en el color indicado public void dibujar( Graphics g ) { g.setColor( miColor ); g.drawLine( x1, y1, x2, y2 ); } // fin del m etodo dibujar } // fin de la clase MiLinea

int del del del del

y2, Color color ) { primer extremo primer extremo segundo extremo segundo extremo

A continuaci on se declara la clase DibujaPanel.java, la cual generar a objetos aleatorios de la clase MiLinea. La l nea 11 declara un arreglo MiLinea

2.7 Usando objetos con gr acas

27

para guardar las l neas a dibujar. Dentro del constructor, l neas 1435, en la l nea 15 se ja el color del fondo a Color.WHITE. La l nea 17 crea el arreglo con una longitud aleatoria entre 5 y 9. El ciclo, en las l neas 2034 crea un nuevo MiLinea para cada elemento en el arreglo. Las l neas 2225 generan coordenadas aleatorias para cada los extremos de cada l nea, en las l neas 2830 se genera un color aleatorio para la l nea. En la l nea 33 se crea un nuevo objeto MiLinea con los valores generados aleatoriamente y se guarda este en el arreglo. El m etodo paintComponent itera con los objetos MiLinea en el arreglo lineas usando una versi on mejorada del ciclo for, l neas 4142. Cada iteraci on llama el m etodo dibujar del objeto actual MiLinea y le pasa el objeto Graphics para dibujarlo en el panel. La clase PruebaDibujo, siguiente c odigo, congura una nueva ventana para mostrar el dibujo. Como se est an jando las coordenadas para las l neas solamente una vez en el constructor, el dibujo no cambia si paintComponent es llamado para refrescar el dibujado en la pantalla.
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 // DibujaPanel.java // Programa que usa la clase MiLinea // para dibujar l neas aleatorias import java.awt.Color; import java.awt.Graphics; import java.util.Random; import javax.swing.JPanel; public class DibujaPanel extends JPanel { private Random numerosAleatorios = new Random(); private MiLinea lineas[]; // arreglo de l neas // constructor, crea un panel con figuras aleatorias public DibujaPanel() { setBackground( Color.WHITE ); lineas = new MiLinea[ 5 + numerosAleatorios.nextInt( 5 ) ]; // crear l neas for ( int i = 0; i < lineas.length; i++ ) { // generar n umeros aleatorios int x1 = numerosAleatorios.nextInt( 300 ); int y1 = numerosAleatorios.nextInt( 300 ); int x2 = numerosAleatorios.nextInt( 300 ); int y2 = numerosAleatorios.nextInt( 300 );

28

Caso de estudio

26 27 // generar un color aleatorio 28 Color color = new Color( numerosAleatorios.nextInt( 256 ), 29 numerosAleatorios.nextInt( 256 ), 30 numerosAleatorios.nextInt( 256 ) ); 31 32 // agregrar la l nea a la lista de l neas que ser an mostradas. 33 lineas[ i ] = new MiLinea( x1, y1, x2, y2, color ); 34 } // fin del for 35 } // fin del constructor DrawPanel 36 37 // para cada figura del arreglo, dibujar las figuras individuales 38 public void paintComponent( Graphics g ) { 39 super.paintComponent( g ); 40 // dibujar las l neas 41 for ( MiLinea linea : lineas ) 42 linea.dibujar( g ); 43 } // fin del m etodo paintComponent 44 } // fin de la clase DibujaPanel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // PruebaDibuja.java // Aplicaci on de prueba para mostrar un DibujaPanel. import javax.swing.JFrame; public class PruebaDibujo { public static void main( String args[] ) { DibujaPanel panel = new DibujaPanel(); JFrame application = new JFrame(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.add( panel ); application.setSize( 300, 300 ); application.setVisible( true ); } // fin de main } // fin de la clase PruebaDibujo

2.7.1.

Ejercicios

1. Extender el programa de esta secci on para dibujar aleatoriamente rect angulos y elipses. Crear las clases MiRectangulo y MiElipse. Ambas clases deber an incluir coordenadas x1, y1, x2, y2, un color y un valor boo-

2.7 Usando objetos con gr acas

29

leano para determinar si la gura es rellena. Declarar un constructor en cada clase con argumentos para inicializar todas las variables de instancia. Para ayudar a dibujar rect angulos y elipses, cada clase deber a dar m etodos getSuperiorIzquierdaX, getSuperiorIzquierdaY, getAncho y getAlto que calculen la coordenada superior izquierda x, la coordenada superior izquierda y, el ancho y el alto, respectivamente. La coordenada superior izquierda x, es el valor m as peque no de las dos coordenadas x, de manera similar para la coordenada superior y, el ancho es el valor absoluto de la diferencia entre las abscisas, y la altura es el valor absoluto de la diferencia entre las dos ordenadas de los extremos. La clase DibujaPanel, la cual extiende a JPanel, maneja la creaci on de las guras, deber a declarar tres arreglos, uno para cada forma de gura. La longitud de cada arreglo deber a ser un n umero aleatorio entre 1 y 5. El constructor de la clase DibujaPanel llenar a cada uno de los arreglos con guras de posici on, tama no, color y llenado aleatorio, como se indica en el ejercicio 2 de la secci on 2.5.1. Adicionalmente, modicar las tres clases de guras para incluir lo siguiente:

a ) Un constructor sin argumentos que ja todas las coordenadas de la gura a cero, el color de la gura a color negro, y la propiedad de llenado a false, esto u ltimo s olo para MiRectangulo y MiElipse. b ) M etodos set para las variables de instancia en cada clase. Los m etodos que jen un valor coordenado deber an vericar que el argumento es mayor que, o igual a cero antes de jar la coordenada si no, estos deber an poner la coordenada a cero. El constructor deber a llamar a los m etodos set en vez de inicializar las variables de instancia directamente. c ) M etodos get para las variables de instancia en cada clase. El m etodo dibujar deber a referenciar las coordenadas por los m etodos get en vez de acceder directamente a las variables.

30

Caso de estudio

2.8.

Texto e im agenes con etiquetas

Los programas frecuentemente usan etiquetas cuando requieren mostrar informaci on o instrucciones al usuario en una interfaz gr aca. Las etiquetas son una forma conveniente para identicar componentes GUI en la pantalla y para mantener informado al usuario respecto al estado actual del programa. En Java, un objeto de la clase JLabel del paquete javax.swing puede mostrar una sola l nea de texto, una imagen o ambos. El siguiente ejemplo muestra varias caracter sticas de JLabel.
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 // LabelDemo.java // Muestra el uso de etiquetas import java.awt.BorderLayout; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JFrame; public class LabelDemo { public static void main( String args[] ) { // crear una etiqueta plana con texto JLabel etiquetaNorte = new JLabel( "Norte" ); // crear un icono desde una imagen para ponerlo en un JLabel ImageIcon iconoEtiqueta = new ImageIcon( "gnome-gnibbles.png" ); // crear una etiqueta con un icono en vez de texto JLabel etiquetaCentro = new JLabel( iconoEtiqueta ); // crear otra etiqueta con un icono JLabel etiquetaSur = new JLabel( iconoEtiqueta ); // configurar etiqueta para mostrar texto, al igual que el icono etiquetaSur.setText( "Sur" ); // crear una ventana para poner las etiquetas JFrame aplicacion = new JFrame(); aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); // agregar las etiquetas a la ventana, el segundo argumento indica // en que lugar de la ventana se pondra la etiqueta aplicacion.add( etiquetaNorte, BorderLayout.NORTH ); aplicacion.add( etiquetaCentro, BorderLayout.CENTER );

2.8 Texto e im agenes con etiquetas

31

35 aplicacion.add( etiquetaSur, BorderLayout.SOUTH ); 36 37 aplicacion.setSize( 300, 300 ); // fijar el tama~ no de la ventana 38 aplicacion.setVisible( true ); // mostrar la ventana 39 } // fin de main 40 } // fin de la clase LabelDemo

En las l neas 36 se importan las clases que se requieren para mostrar las etiquetas. BorderLayout del paquete java.awt tiene constantes para indicar donde se pueden colocar componentes GUI en un JFrame. La clase ImageIcon representa una imagen que puede ser mostrada en un JLabel, y la clase JFrame representa la ventana que contendr a todas las etiquetas. La l nea 12 crea un JLabel que muestra su argumento para el constructor la cadena "Norte". La l nea 15 declara la variable local iconoEtiqueta y le asigna un nuevo ImageIcon. El constructor para ImageIcon recibe una cadena que indica el camino a la imagen. Como solamente se indica un nombre de archivo, Java supone se encuentra en el mismo directorio de la clase LabelDemo. ImageIcon puede cargar im agenes en formato GIF, JPEG y PNG. La l ena 18 declara e inicializa la variable local etiquetaCentro con un JLabel que muestra a iconoEtiqueta. Sin embargo, en la l nea 24 se llama al m etodo setText para cambiar el texto que la etiqueta muestra. El m etodo setText puede ser llamado por cualquier JLabel para cambiar su texto. Este JLabel mostrar a el icono y el texto. En la l nea 27 se crea un JFrame que mostrar a los JLabels, y la l nea 29 indica que el programa deber a terminar cuando el JFrame se cierre. Se ponene las etiquetas en la ventana en las l neas 3335 llamando una versi on sobrecargada del m etodo add que toma dos par ametros. El primer m etodo es el componente que se quiere poner, y el segundo es la regi on en la cual este deber a ser puesto. Cada JFrame tiene asociado un manejador que ayuda en la posici on de los componentes que tiene puestos. El manejado por defecto para un JFrame es el conocido como BorderLayout y tiene cinco regiones NORTH (superior), SOUTH (inferior), EAST (lado derecho), WEST (lado izquierdo) y CENTER (centro). Cada uno de estos est a declarado como una constante en la clase BorderLayout. Cuando se llama al m etodo add con un argumento, el JFrame coloca al componente usando CENTER autom aticamente. Si una posici on ya conten a un componente, entonces el nuevo componente toma su lugar. En las l neas 27 y 39 se pone el tama no de la ventana y se hace visible en pantalla.

32

Caso de estudio

2.8.1.

Ejercicio

1. Modicar el ejercicio 1 de la secci on 2.7.1 para incluir un JLabel como una barra de estado que muestre la cantidad de cada gura dibujada, podr a tener un texto como: L neas 3, Elipses 2, Rect angulos 4 . La clase DibujaPanel deber a declarar un m etodo que regrese una cadena conteniendo el texto del estado. En el m etodo main, primero crear el DibujaPanel, despu es crear el JLabel con el texto del estado como un argumento del constructor JLabel. Poner el JLabel en la regi on inferior de la ventana.

2.9.

Dibujado con polimorsmo

Como se puede observar en el ejercicio 1 de la secci on 2.7.1, y en la modicaci on solicitada en el ejercicio 1 de la secci on 2.8.1 existen muchas similaridades entre las clases de las guras. Usando herencia se pueden factorizar las caracter sticas comunes de las tres clases y colocarlas en una sola superclase. Se pueden entonces manipular los todos los objetos, de tres tipos de guras, polim orcamente usando variables del tipo de la superclase. Removiendo la redundancia en el c odigo resultar a un programa m as peque no y exible que es m as f acil de mantener.

2.9.1.

Ejercicios

1. Modicar las clases MiLinea, MiElipse y MiRectangulo del ejercicio uno de la secci on 2.7.1 y 2.8.1 para crear la siguiente jerarqu a de clases: La clase MiFigura es una subclase de java.lang.Object Las clases MiLinea, MiElipse y MiRectangulo son subclases de MiFigura. Las subclases de la jerarqu a MiFigura deber an ser clases gura inteligentes para saber como dibujarse ellas si se proporciona un objeto Graphics que les diga donde dibujar. Una vez que el programa cree un objeto de la jerarqu a, este lo puede manipular polim orcamente por el resto de su existencia como un MiFigura. En la soluci on, la clase MiFigura deber a ser abstract. Como MiFigura representa cualquier gura en general, no se puede implementar el

2.9 Dibujado con polimorsmo

33

m etodo dibujar sin saber exactamente que gura es. Los datos representando las coordenadas y el color de las guras en la jerarqu a deber an ser declarados como miembros private de la clase MiFigura. Adem as de los datos comunes, la clase MiFigura deber a declarar los siguientes m etodos: a ) Un constructor sin argumentos que ponga todas las coordenadas de la gura en cero y el color en negro. b ) Un constructor que inicialize las coordenadas y el color con los valores de los argumentos proporcionados. c ) M etodos set para las coordenadas individuales y el color que permitan al programador poner cualquier parte de los datos independientemente para una gura en la jerarqu a. d ) M etodos get para las coordenadas individuales y el color que permitan al programador recuperar cualquier parte de los datos independientemente para una gura en la jerarqu a. e ) El m etodo abstract public abstract void dibujar( Graphics g ); el cual ser a llamado por el m etodo paintComponent del programa para dibujar una gura en la pantalla. Para asegurar la encapsulaci on, todos los datos en la clase MiFigura deber an ser private. Esto requiere declarar m etodos set y get para manipular los datos. La clase MiLinea deber a proporcionar un constructor sin argumentos y un constructor con argumentos para las coordenadas y el color. Las clases MiElipse y MiRectangulo deber an proporcionar un constructor sin argumentos y un constructor con argumentos para las coordenadas, el color y para saber si la gura es rellena. El constructor sin argumentos deber a, adicionalmente de poner los valores por defecto, jar la gura sin relleno. Se pueden dibujar l neas, rect angulos, y elipses si se conocen dos puntos en el plano. Las l neas requieren las coordenadas x1, y 1, x2 y y 2. El m etodo drawLine de la clase Graphics conectar a los dos puntos dados con un l nea. Si se tienen los mismos cuatro valores para elipses y rect angulos, se pueden calcular los argumentos necesarios para dibujarlos. Cada uno requiere el valor x de la esquina superior izquierda

34

Caso de estudio (el m as peque no de las x de las dos abscisas), y de la esquina superior izquierda (el m as peque no de las y de las dos ordenadas), un ancho (el valor absoluto de la diferencia de las dos abscisas) y un alto (el valor absoluto de la diferencia de las dos ordenadas). Los rect angulos y las elipses podr an tambi en tener una bandera relleno que determine si se dibuja la gura como rellena. No deber a haber en el programa variables MiLinea, MiRectangulo, o MiElipse solamente variables MiFigura que contengan referencias a objetos tipo MiLinea, MiRectangulo, o MiElipse. El programa deber a generar guras aleatorias y guardarlas en un arreglo del tipo MiFigura. El m etodo paintComponent deber a recorrer el arreglo tipo MiFigura y dibujar cada gura (es decir, llamando polim orcamente al m etodo dibujar de cada gura. Permitir al usuario indicar, con un cuadro de di alogo de entrada, el n umero de guras que se generar an. El programa entonces las genera y las muestra con una barra de estado que informa al usuario cuantas guras de cada una fueron creadas. 2. En el ejercicio 1, se creo una jerarqu a MiFigura en donde las clases MiLinea, MiRectangulo y MiElipse extienden directamente a MiFigura. Si la jerarqu a fue dise nada adecuadamente, se podr a observar las similaridades entre las clases MiRectangulo y MiElipse. Redise nar y reimplementar el c odigo para las clases MiRectangulo y MiElipse para factorizar las caracter sticas comunes en la clase abstracta MiFiguraAcotada para generar la siguiente jerarqu a. La clase MiFigura es una subclase de java.lang.Object Las clases MiLinea y MiFiguraAcotada son subclases de MiFigura. Las clases MiElipse y MiRectangulo son subclases de MiFiguraAcotada. La clase MiFiguraAcotada deber a declarar dos constructores que imiten a los de la clase MiFigura y que agreguen un par ametro para poner si la gura es rellena. La clase MiFiguraAcotada deber a tambi en declarar m etodos set y get para manipular el campo relleno y m etodos que calculen la coordenada x de la esquina superior izquierda, la coordenada y de la esquina superior izquierda, el ancho y el alto. Si esta bien dise nado, las nuevas clases MiElipse y MiRectangulo deber an tener cada una dos constructores y un m etodo dibujar.

Cap tulo 3 Componentes GUI


3.1. Introducci on

Una interfaz gr aca de usuario GUI (graphical user interface) presenta un mecanismo amigable al usuario para interactuar con una aplicaci on. Una GUI da a una aplicaci on una apariencia y comportamiento. Las GUI est an constru das con componentes GUI. Estos algunas veces son llamados controles o widget sabreviatura de window gadget en otros lenguajes. Un componente GUI es un objeto con el cual el usuario interact ua usando el rat on, el teclado u otra forma de entrada, como el reconocimiento de voz.

3.2.

Generalidades de Componentes Swing

Se revisan varios componentes GUI que permiten a los desarrolladores de aplicaciones crear GUIs robustos. En la siguiente tabla se muestran varios componentes GUI tipo Swing del paquete javax.swing que son usados para construir GUIs de Java.

36 Componente JLabel JTextField

Componentes GUI Descripci on Muestra texto o iconos no editables. Permite al usuario ingresar datos desde el teclado. Puede tambi en ser usado para mostrar texto editable o no editable. Dispara un evento cuando se pulsa con el rat on. Indica una opci on que puede ser o no seleccionada. Da una lista de art culos que abren hacia abajo (drop-down ) de las cuales el usuario puede hacer una selecci on pulsando sobre un art culo o posiblemente tecleando en el cuadro. Da una lista de art culos de los cuales el usuario puede hacer una selecci on pulsando en cualquier art culo en la lista. Elementos m ultiples pueden ser seleccionados. Da una a rea en la cual los componentes pueden ser colocados y organizados. Puede tambi en ser usado como area de dibujo para gr acas.

JButton JCheckBox JComboBox

JList

JPanel

Varios componentes Swing son componentes puros de Java est an escritos, manipulados y desplegados completamente en Java. Estos son parte de JFC (Java Foundation Classes ) bibliotecas de Java para desarrollo GUI de plataforma cruzada. Swing vs. AWT. Hay actualmente dos conjuntos de componentes GUI en Java. Antes de que Swing fuera introducido en Java SE 1.2, la GUI de Java era construida con componentes de AWT del paquete java.awt. Cuando una aplicaci on Java con un GUI de AWT se ejecuta en diferentes plataformas JAVA, los componentes de la aplicaci on GUI se muestran diferentes en cada plataforma. Por ejemplo, una aplicaci on que muestre un objeto del tipo Button del paquete java.awt, en un computadora que ejecute el sistema operativo Windows, el bot on tendr a la misma apariencia de los botones de otras aplicaciones para ese sistema, es decir, los componentes se ver an, para alg un

3.2 Generalidades de Componentes Swing

37

sistema operativo gr aco, como los componentes de las otras aplicaciones. Por otra parte, la forma en la cual un usuario interact ua con un componente AWT diere entre plataformas. Los componentes GUI de Swing permiten especicar un look-and-feel (la apariencia y la forma en la cual el usuario interacciona con la aplicaci on) uniforme para la aplicaci on para todas las plataformas o usar de cada plataforma el look-and-feel de la plataforma. Una aplicaci on puede cambiar su apariencia durante la ejecuci on para permitir al usuario escoger su apariencia preferida. Componentes peso ligero vs peso pesado. Muchos componentes Swing no est an empatados a los componentes GUI soportados por la plataforma subyacente en la cual la aplicaci on se ejecuta. Tales componentes GUI son conocidos como componentes de peso ligero o lightweight. Los componentes AWT, muchos son paralelos a los componentes Swing, est an empatados a la plataforma local y son llamados componentes de peso pesado o heavyweight, porque descansan en la plataforma local del sistema de ventanas para determinar su funcionalidad y su apariencia. Varios componentes Swing son componentes pesados. Parecidos a los componentes AWT, los componentes GUI pesados de Swing requieren interacci on directa con el sistema de ventanas local, lo cual podr a restringir su apariencia y funcionalidad, haci endolos menos exibles que los componentes ligeros. Superclases de los componentes ligeros La clase Object es la superclase de la jerarqu a de clases de Java. La clase Component del paquete java.awt es una subclase de Object que declara varios atributos y comportamientos comunes a los componentes GUI en los paquetes java.awt y javax.swing. Muchos componentes GUI extienden la clase Component directamente o indirectamente. La clase Container en el paquete java.awt es una subclase de Component. Los componentes son puestos en Containers, como ventanas, por lo que los componentes pueden ser organizados y mostrados en la pantalla. Cualquier objeto, que es del tipo Container, puede ser usado para organizar otros Components en una GUI. Como un Container es un Component, se pueden adjuntar Containers a otro Container para ayudar a organizar la GUI. La clase JComponent del paquete javax.swing es una subclase Container. JComponent es la superclase de todos los componentes ligeros Swing y de-

38

Componentes GUI

clara sus atributos comunes y comportamientos. Como JComponent es una subclase de Container, todos los componentes ligeros de Swing son tambi en Container. Algunas caracter sticas comunes de los componentes ligeros soportadas por JComponent incluyen: 1. Un look-and-feel enchufable que puede ser usado para congurar la apariencia de componentes. 2. Accesos r apidos de teclado, llamados nemot ecnicos, para el acceso directo a los componentes GUI a trav es del teclado. 3. Capacidades comunes de manejo de eventos para casos donde varios componentes GUI inician las mismas acciones en una aplicaci on. 4. Breves descripciones del prop osito de los componentes GUI, llamados sugerencias (tool tips ), que son mostrados por un per odo corto cuando el cursor del rat on es posicionado sobre el componente. 5. Soporte para tecnolog as asistentes, tales como lectores braille para los impedidos visualmente. 6. Soporte para localizaci on de interfaz-usuario esto es, congurar la interfaz del usuario para mostrar en diferentes lenguas y convenciones culturales locales.

3.3.

Mostrar texto e im agenes en una ventana

Se presenta en el siguiente ejemplo un framework (marco) para construir aplicaciones GUI. El framework usa varios conceptos que se ver an en varias aplicaciones GUI. Este es el primer ejemplo en el cual la aplicaci on aparece en su propia ventana. Muchas ventanas que se crear an ser an una instancia de la clase JFrame o una subclase de JFrame. JFrame proporciona los atributos b asicos y comportamientos de una ventana una barra de t tulo en la parte superior de la ventana, y botones para minimizar, maximizar, y cerrar la ventana. Como una aplicaci on GUI es t picamente especica a la aplicaci on, varios de los ejemplos consistir an de dos clases una subclase de JFrame que ayuda a mostrar nuevos conceptos GUI y una clase aplicaci on en la cual main crea y muestra la ventana primaria de la aplicaci on.

3.3 Mostrar texto e im agenes en una ventana

39

Una GUI t pica consiste de varios componentes. En un GUI grande puede ser dif cil identicar el prop osito de cada componente a menos que el dise nador de la GUI proporcione instrucciones de texto o informaci on indicando el prop osito de cada componente. Tal texto es conocido como una etiqueta y es creado con la clase JLabel una subclase de JComponent. Un JLabel muestra una l nea de texto de s olo lectura, una imagen, o ambas. Las aplicaciones raramente cambian el contenido de una etiqueta despu es de haberla creado. La aplicaci on VentanaLabel muestra varias capacidades de JLabel y muestra el marco que ser a usado en la mayor a de los ejemplos GUI. Hay muchas m as caracter sticas de cada componente GUI que las vistas en los ejemplos. Para revisar los detalles completos de cada componente GUI, se recomienda revisar la documentaci on. La clase VentanaLabel, que se muestra a continuaci on, es una subclase de JFrame. Se usar a una instancia de la clase VentanaLabel para mostrar una ventana conteniendo tres JLabels. Las l neas 49 importan las clases usadas en la clase VentanaLabel. La clase extiende a JFrame para heredar las caracter sticas de una ventana. Las l neas 1315 declaran las variables de instancias de las tres JLabel, cada una de las cuales es instanciada en el constructor de VentanaLabel en las l neas 1843. T picamente, el constructor de la subclase del JFrame construye la GUI que es mostrada en la ventana cuando la aplicaci on se ejecuta. La l nea invoca al constructor de la superclase JFrame con el argumento "Probando JLabel". El constructor de JFrame emplea el String como el texto de la barra de t tulos de la ventana.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // VentanaLabel.java // Demostraci on de la clase JLabel. import import import import import import java.awt.FlowLayout; // indica como los componentes son arreglados javax.swing.JFrame; // proporciona capacidades b asicas de ventana javax.swing.JLabel; // muestra texto e im agenes javax.swing.SwingConstants; // constantes comunes usadas con Swing javax.swing.Icon; // interfaz usada para manipular im agenes javax.swing.ImageIcon; // carga im agenes

public class VentanaLabel extends JFrame { private JLabel etiq1; // JLabel con s olo texto private JLabel etiq2; // JLabel constru da con texto e icono private JLabel etiq3; // JLabel con texto e icono agregado

40

Componentes GUI

17 // constructor VentanaLabel agrega JLabels al JFrame 18 public VentanaLabel() { 19 super( "Probando JLabel" ); 20 setLayout( new FlowLayout() ); // fijar el manejador de componentes 21 22 // constructor JLabel con un argumento de cadena 23 etiq1 = new JLabel( "Etiqueta con texto" ); 24 etiq1.setToolTipText( "Esto es etiq1" ); 25 add( etiq1 ); // agregar etiq1 a JFrame 26 27 // constructor JLabel con cadena, icono y argumentos alineados 28 Icon gusano = new ImageIcon( 29 getClass().getResource( "gnome-gnibbles.png" )); 30 etiq2 = new JLabel( "Label con texto e icono", gusano, 31 SwingConstants.LEFT ); 32 etiq2.setToolTipText( "Esto es etiq2" ); 33 add( etiq2 ); // agregar etiq2 a JFrame 34 35 etiq3 = new JLabel(); // constructor JLabel sin argumentos 36 etiq3.setText( "Label con icono y texto en el fondo" ); 37 38 etiq3.setIcon( gusano ); // agregar icono a JLabel 39 etiq3.setHorizontalTextPosition( SwingConstants.CENTER ); 40 etiq3.setVerticalTextPosition( SwingConstants.BOTTOM ); 41 etiq3.setToolTipText( "Esto es etiq3" ); 42 add( etiq3 ); // agregar etiq3 a JFrame 43 } // fin del constructor VentanaLabel 44 } // fin de la clase VentanaLabel

1 2 3 4 5 6 7 8 9 10 11 12 13 14

// PruebaLabel.java // Probador de VentanaLabel. import javax.swing.JFrame; public class PruebaLabel { public static void main( String args[] ) { VentanaLabel ventanaLabel = new VentanaLabel(); // crear VentanaLabel ventanaLabel.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaLabel.setSize( 275, 180 ); // fijar el tama~ no de la ventana ventanaLabel.setVisible( true ); // mostrar la ventana } // fin de main } // fin de la clase PruebaLabel

3.3 Mostrar texto e im agenes en una ventana

41

Indicando el dise no Cuando se construye una GUI, cada componente GUI deber a estar adjuntado a un contenedor, tal como una ventana creada con un JFrame. Tambi en, el programador deber a decidir donde posicionar cada componente GUI. Esto es conocido como especicar el dise no de los componentes GUI. Java proporciona varios manejadores de dise no que pueden ayudar a colocar los componentes. Varios ambientes integrados de desarrollo o IDEs (Integrated Development Environment ) dan herramientas de dise no GUI, en las cuales se puede indicar el tama no exacto y lugar de un componente de forma visual empleando el rat on, entonces el IDE generar a el c odigo GUI por el usuario. Con los IDEs se puede simplicar la creaci on del GUI, sin embargo cada uno tiene diferentes capacidades. Para los ejemplos que se revisar an, se usar an los manejadores de dise no de Java. Uno de estos manejadores de dise no es FlowLayout, en el cual los componentes GUI son colocados en un contenedor de izquierda a derecha en el orden en el cual el programa los agrega al contenedor. Cuando no hay mas espacio para meter componentes de izquierda a derecha. los componentes se continuan mostrando de izquierda a derecha en la siguiente l nea. Si el contenedor es redimensionado, un FlowLayout redimensiona los componentes para acomodarlos al nuevo ancho del contenedor, posiblemente con menos o mas renglones de componentes GUI. El m etodo setLayout es heredado en la clase VentanaLabel indirectamente desde la clase Container. El argumento al m etodo deber a ser un objeto de una clase que implementa la interfaz LayoutManager, por ejemplo FlowLayout. En la l nea 20 se crea un nuevo objeto FlowLayout y se pasa su referencia como argumento a setLayout Creaci on y pegado de etiquetas Una vez que se ha indicado el dise no de la ventana, se puede inciar creando y pegando componentes GUI a la ventana. Las l neas 23, 30, 31 crean objetos JLabel que pasan diferentes referencias y constantes a los constructores. En la l nea 35 se usa un constructor JLabel sin argumentos, pero posteriormente se indica el texto y el icono con los m etodos setText y setIcon respectivamente, como se muestra en las l neas 36 y 38. En las l neas 24, 32 y 41 se usa el m etodo setToolTipText (heredado por JLabel desde JComponent para indicar la sugerencia que es mostrada cuando el usuario pone el cursor del rat on sobre el JLabel en el GUI. En la l nea 29, la expresi on getClass().getResource("gnome-gnibbles.png") llama al m etodo getClass (heredado desde la clase Object) pa-

42

Componentes GUI

ra recuperar una referencia al objeto Class que representa la declaraci on de la clase VentanaLabel. Esa referencia es entonces usada para llamar al m etodo getResource de Class, la cual regresa la localidad de la imagen como un URL (uniform resource locator ). El constructor ImageIcon usa el URL para localizar la imagen, y entonces cargarla en memoria. El cargador de clases sabe donde cada clase que se carga est a localizada en disco. El m etodo getResource usa el cargador de clases del objeto Class para determinar el lugar de un recurso, tal como una archivo de imagen. En este ejemplo, el archivo de imagen est a guardado en el mismo lugar que el archivo VentanaLabel.class. La t ecnica descrita permite a una aplicaci on cargar archivos de imagen desde localidades que son relativas al archivo VentanaLabel.class en el disco. Como se puede apreciar en la l nea 30, al crear un JLabel se puede pasar en el constructor una referencia tipo Icon para que la etiqueta est e compuesta de texto e imagen. Tambi en es posible, que despue s de haber creado el objeto, se agregue la imagen, usando el m etodo setIcon, como se hace en la l nea 28. Las l neas 39 y 40 usan los m etodos setHorizontalTextPosition y setVerticalTextPosition de la clase JLabel para acomodar el texto horizontalmente y verticalmente respectivamente. Las constantes empleadas con estos m etodos, que se encuentran denidas en la clase SwingConstants se describen a continuaci on: Posici on Horizontal SwingConstants.LEFT Texto a la izquierda. SwingConstants.CENTER Texto en el centro. SwingConstants.RIGHT Texto a la derecha. Posici on Vertical SwingConstants.TOP Texto en la cima SwingConstants.CENTER Texto en el centro. SwingConstants.BOTTOM Texto al fondo.

3.4.

Campos de texto y manejo de eventos con clases anidadas

Normalmente, un usuario interact ua con una aplicaci on GUI para indicar las tareas que la aplicaci on deber a hacer. Cuando el usuario interact ua con un

3.4 Campos de texto y eventos

43

componente GUI, la interacci on conocida como un evento conduce al programa a realizar una tarea. Algunos eventos comunes que podr an causar que una aplicaci on haga una tarea incluyen el pulsado de un bot on, el tecleado en un campo de texto, la selecci on de un elemento de un men u, el cerrado de una ventana y el movimiento del rat on. El c odigo que realiza una tarea en respuesta a un evento es llamado un manejador de eventos y todo el proceso de respuesta a eventos es conocido como manejo de eventos. Se revisan en esta secci on dos nuevos componentes GUI que pueden generar eventos JTextField y JPasswordField del paquete java.swing. La clase JTextField extiende la clase JTextComponent del paquete javax.swing.text, la cual proporciona varias capacidades comunes a los componentes Swing basados en texto. La clase JPasswordField extiende a JTextField y agrega varios m etodos que son espec cos para procesar contrase nas. Cada uno de estos componentes es una a rea de una sola l nea en el cual el usuario puede ingresar texto usando el teclado. Las aplicaciones pueden tambi en mostrar texto en un JTextField. Un JPasswordField muestra que car acteres han sido tecleado conforme el usuario los ha ingresado, pero esconde el car acter actual con un car acter eco, asumiendo que estos representan una contrase na que s olo deber a ser conocida por el usuario. Cuando el usuario teclea datos en un JTextField o en un JPasswordField, y despu es presiona Intro, un evento ocurre. El siguiente ejemplo muestra como un programa puede realizar una tarea en respuesta a ese evento. Las t ecnicas mostradas en el ejemplo son aplicables a todos los componentes GUI que generan eventos. La aplicaci on siguiente usa las clases JTextField y JPasswordField para crear y manipular cuatro campos de texto. Cuando el usuario teclea en uno de los campos de texto, y presiona Intro, la aplicaci on muestra un cuadro de di alogo conteniendo el texto que el usuario tecle o. El usuario s olo puede teclear en el campo de texto que est e en foco. Un componente recibe el foco cuando el usuario pulsa en el componente. Esto es importante, porque el campo de texto con el foco es el que genera un evento cuando el usuario presiona Intro. En este ejemplo, cuando el usuario presiona Intro en el JPasswordField, la contrase na es revelada.
1 2 3 4 5 // VentanaTextField.java // Mostrando la clase JTextField. import java.awt.FlowLayout; import java.awt.event.ActionListener;

44
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 import import import import java.awt.event.ActionEvent; javax.swing.JFrame; javax.swing.JTextField; javax.swing.JPasswordField; javax.swing.JOptionPane;

Componentes GUI

public class VentanaTextField extends JFrame { private private private private JTextField campoTexto1; // campo de texto con el tama~ no dado JTextField campoTexto2; // campo de texto construido con texto JTextField campoTexto3; // campo de texto con texto y tama~ no JPasswordField campoContra; // campo de contrase~ na con texto

// constructor VentanaTextField que agrega JTextFields al JFrame public VentanaTextField() { super( "Probando JTextField y JPasswordField" ); setLayout( new FlowLayout() ); // poner el dise~ nador de ventana // construir campo de texto con 10 columnas campoTexto1 = new JTextField( 10 ); add( campoTexto1 ); // agregar campoTexto1 al JFrame // construir campo de texto con texto por defecto campoTexto2 = new JTextField( "Ingresar texto aqu " ); add( campoTexto2 ); // agregar campoTexto2 al JFrame // construir campo de texto con texto por defecto y 21 columnas campoTexto3 = new JTextField( "Campo de texto no editable", 21 ); campoTexto3.setEditable( false ); // deshabilitar la edici` on add( campoTexto3 ); // agregar campoTexto3 al JFrame // construir campo de contrase~ na con texto por defecto campoContra = new JPasswordField( "Texto oculto" ); add( campoContra ); // agregar campoContra al JFrame // registrar manejadores de eventos TextFieldHandler manejador = new TextFieldHandler(); campoTexto1.addActionListener( manejador ); campoTexto2.addActionListener( manejador ); campoTexto3.addActionListener( manejador ); campoContra.addActionListener( manejador ); } // fin del constructor VentanaTextField // clase privada interna para manejo de eventos private class TextFieldHandler implements ActionListener {

3.4 Campos de texto y eventos


51 52 // procesar eventos de campos de texto 53 public void actionPerformed( ActionEvent evento ) { 54 55 String cadena = ""; // declarar un String para mostrar 56 57 // usuario presion o Intro en JTextField campoTexto1 58 if ( evento.getSource() == campoTexto1 ) 59 cadena = String.format( "campoTexto1: %s", 60 evento.getActionCommand() ); 61 62 // usuario presion o Intro en JTextField campoTexto2 63 else if ( evento.getSource() == campoTexto2 ) 64 cadena = String.format( "campoTexto2: %s", 65 evento.getActionCommand() ); 66 67 // usuario presion o Intro en JTextField campoTexto3 68 else if ( evento.getSource() == campoTexto3 ) 69 cadena = String.format( "campoTexto3: %s", 70 evento.getActionCommand() ); 71 72 // usuario presion o Intro en campoContra 73 else if ( evento.getSource() == campoContra ) 74 cadena = String.format( "campoContra: %s", 75 new String( campoContra.getPassword() ) ); 76 77 // mostrar el contenido de JTextField 78 JOptionPane.showMessageDialog( null, cadena ); 79 } // fin del m etodo actionPerformed 80 } // fin de la clase interna TextFieldHandler 81 } // fin de la clase VentanaTextField 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // PruebaTextField.java // Probando VentanaTextField. import javax.swing.JFrame; public class PruebaTextField {

45

public static void main( String args[] ) { VentanaTextField ventanaTextField = new VentanaTextField(); ventanaTextField.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaTextField.setSize( 350, 100 ); // fijar tama~ no de la ventana ventanaTextField.setVisible( true ); // mostrar ventana } // fin main } // fin de la clase PruebaTextField

46

Componentes GUI

Creaci on de la GUI. La l nea 22 pone el dise no de VentanaTextField a FlowLayout. La l nea 25 crea campoTexto1 con 10 columnas de texto. El ancho en p xeles de una columna de texto est a determinado por el ancho promedio de un car acter en el campo de texto de la fuente actual. Cuando el texto es mostrado en un campo de texto y el texto es m as ancho que el campo de texto, una porci on del texto en el lado derecho no es visible. Si se est a tecleando en un campo de texto y el cursor alcanza el lado derecho del campo de texto, el texto del lado izquierdo es recorrido hacia all a y no se ver a m as. El usuario puede usar las teclas de navegaci on izquierda y derecha para moverse a trav es del texto completo a un si el texto entero no es visible en un momento. La l nea 26 agrega campoTexto1 al JFrame. La l nea 29 crea campoTexto2 con el texto inicial Ingresar texto aqu para ser mostrado en el campo de texto. El ancho del campo de texto est a determinado por el ancho del texto indicado en el constructor. La l nea 30 lo agrega al JFrame. La l nea 33 crea campoTexto3 y llama al constructor JTextField con dos argumentos el texto Campo de texto no editable a mostrar y el n umero de columnas (21). La l nea 34 usa el m etodo setEditable (heredada a JTextField desde la clase JTextComponent) para hacer el campo de texto no editable. En la l nea 35 se agrega al JFrame. La l nea 38 crea campoContrase~ na con el texto Texto oculto para mostrarlo en el campo de texto. Cuando se ejecuta la aplicaci on, observar que el texto es mostrado como una cadena de asteriscos. La l nea 39 lo agrega al JFrame. Pasos para manejar eventos. El ejemplo deber a mostrar un cuadro de mensaje conteniendo el texto desde el campo cuando el usuario presiona Intro en aquel campo de texto. Antes de que una aplicaci on pueda responder a un evento para un componente GUI particular, el programador deber a hacer varios pasos de codicaci on: 1. Crear una clase que represente al manejador de evento. 2. Implementar una interfaz apropiada, conocida como interfaz receptora del evento, en la clase del primer paso. 3. Indicar que un objeto de la clase desde los pasos 1 y 2 deber a ser noticado cuando el evento ocurrra. Esto es conocido como registrar el manejador de evento.

3.4 Campos de texto y eventos

47

Uso de clases anidadas para manejo de eventos. Todas las clases vistas previamente son llamadas clases de nivel superior esto es, las clases no fueron declaradas dentro de otra clase. Java permite declarar clases dentro de otra estas clases son llamadas clases anidadas. Las clases anidadas pueden ser static o no. Las clases anidadas no static son llamadas clases anidadas y son frecuentemente empleadas para manejar eventos. Una clase interna permite acceso directamente a las variables y m etodos de su clase de nivel superior, a un si ellos son private. Antes de que un objeto de una clase interna pueda ser creado, deber a haber primero un objeto de la clase de nivel superior que contenga la clase interna. Esto es requerido porque un objeto de la clase interna impl citamente tiene una referencia a un objeto de su clase de nivel superior. Hay una relaci on especial entre estos objetos al objeto de la clase interna se le permite accesar directamente todas las variables de instancia y m etodos de la clase externa. Una clase anidada que es static no requiere un objeto de la clase de nivel superior y no tiene impl citamente una referencia a un objeto de la clase de nivel superior. El manejo de evento en este ejemplo es hecho por un objeto de la clase interna private TextFieldHandler en las l neas 5081. Esta clase es private porque esta ser a usada solamente para crear manejadores de eventos para los campos de texto en la clase de nivel superior VentanaTextField. Al igual que con otros miembros de una clase, las clases internas pueden ser declaradas public, protected o private. Los componentes GUI pueden generar una variedad de eventos en respuesta a las interacciones del usuario. Cada evento est a representado por una clase y puede ser procesado solamente por el tipo apropiado de manejador de eventos. Los eventos que un componente GUI soporta est an descritos en la documentaci on API de Java. Cuando el usuario presiona Intro en un JTextField o un JPasswordField, el componente GUI genera un ActionEvent (paquete java.awt.event). Tal evento es procesado por un objeto que implementa la interfaz ActionListener (paquete java.awt.event). Como JPasswordField es una subclase de JTextField, JPasswordField soporta los mismos eventos. Para preparar el manejo de los eventos, la clase interna TextFieldHandler implementa la interfaz ActionListener y declara el u nico m etodo en la interfaz actionPerformed (l neas 5080). Este m etodo indica las tareas a realizar cuando un evento ActionEvent suceda.

48

Componentes GUI

Registro del manejador de eventos En el constructor VentanaTextField, la l nea 42 crea un objeto TextFieldHandler y lo asigna a la variable manejador. El m etodo actionPerformed del objeto ser a llamado autom aticamente cuando el usuario presione Intro en cualquiera de los campos de texto GUI. Sin embargo, antes de que esto pueda ocurrir, el programa deber a registrar este objeto como el manejador de eventos para cada campo de texto. Las l neas 4346 son las sentencias de registro de eventos que indican que manejador se emplear a con los tres JTextField y el JPasswordField. La aplicaci on llama al m etodo addActionListener de la clase JTextField, para registrar el manejador de eventos para cada componente. Este m etodo recibe como su argumento un objeto actionListener, el cual puede ser un objeto de cualquier clase que implemente ActionListener. Cuando el usuario presiona Intro en cualquiera de estos cuatro campos de textos, el m etodo actionPerformed (l neas 5379) de la clase TextFieldHandler es llamado para manejar el evento. Si un manejador de evento no est a registrado para un campo de texto particular, el evento que ocurre cuando el usuario presiona Intro en aquel campo de texto es consumido esto es, el evento es simplemente ignorado por la aplicaci on.

M etodo actionPerformed En el ejemplo, se est a usando un solo objeto manejador de eventos, con el m etodo actionPerformed, para manejar los eventos generados por los cuatro campos de texto. Como se quiere mostrar el nombre de cada variable de instancia del campo de texto donde se genera el evento, se debe determinar cual es el campo de texto que gener o el evento cada vez que actionPerformed es llamado. El componente GUI con el cual el usuario interact uo es la fuente del evento. Para el ejemplo, la fuente del evento es uno de los campos de texto o el de la contrase na. Cuando el usuario presiona Intro mientras uno de estos componentes tiene el foco, el sistema crea un objeto u nico ActionEvent que contiene informaci on acerca del evento que ha ocurrido, tal como la fuente del evento y el texto en el campo de texto. El sistema entonces pasa este objeto ActionEvent en una llamada al m etodo receptor de eventos actionPerformed. En el ejemplo, se muestra algo de esa informaci on en un cuadro de mensaje. El m etodo getSource de ActionEvent, llamado en las l neas 58, 63, 68 y 75, regresa una referencia a la fuente del evento. La condici on en la l nea 58 pregunta, es la fuente del evento campoTexto1?. Esta condici on compara las referencias a cada lado del operador == para determinar si ellas se reeren

3.5 Tipos de eventos e interfaces receptoras

49

al mismo objeto. Si ellas se reeren a campoTexto1, entonces el programa sabr a que el usuario presion o Intro en campoTexto1 y en las l neas 5960 se crea un String conteniendo el mensaje que la l nea 78 mostrar a en un cuadro de mensaje. La l nea 60 usa el m etodo getActionCommand de la clase ActionEvent para obtener el texto que el usuario tecle o en el campo de texto que gener o el evento. La clase PruebaTextField contiene el m etodo main que ejecuta su aplicaci on y muestra un objeto de la clase VentanaTextField. Cuando la aplicaci on es ejecutada, observar que a un el campo no editable JTextField (campoTexto3) puede generar un ActionEvent. Para probarlo, pulsar el campo de texto para darle el foco, y presionar Intro. Tambi en observar que el texto actual de la contrase na es mostrado cuando el usuario presiona Intro en el campo JPasswordField.

3.5.

Tipos de eventos e interfaces receptoras

Varios tipos diferentes de eventos pueden ocurrir cuando el usuario interact ua con una GUI. La informaci on acerca de cualquier evento GUI que ocurra es guardada en un objeto de una clase que extiende AWTEvent. La gura 3.1 muestra una jerarqu a conteniendo varias clases de eventos del paquete java.awt.event. Estos tipos de eventos son usados con los componentes AWT y Swing. Los tipos de eventos adicionales que son espec cos a los componentes GUI tipo Swing est an declarados en el paquete javax.swing.event. Las tres partes para el mecanismo de manejo de eventos son: la fuente del evento, el objeto evento y el receptor del evento. La fuente del evento es el componente GUI particular con el cual el usuario interact ua. El objeto evento encapsula informaci on acerca del evento que ocurri o, tal como una referencia a la fuente del evento y cualquier informaci on espec ca que podr a ser requerida por el receptor de eventos para manejar el evento. El receptor del evento es un objeto que es noticado por la fuente del evento cuando el evento ocurre; en efecto, este escucha por un evento, y uno de sus m etodos se ejecuta en respuesta al evento. Un m etodo del receptor de eventos recibe un objeto evento cuando el receptor de eventos es noticado del evento. El receptor del evento entonces usa el objeto evento para responder al evento. El modelo de manejo de eventos descrito es conocido como el modelo de delegaci on de eventos un procesamiento de eventos es delegado a un objeto particular (el receptor de eventos) en la aplicaci on.

50

Componentes GUI

Figura 3.1: Algunas clases de eventos del paquete java.awt.event.

3.6 Como trabaja el manejador de eventos

51

Para cada tipo de objeto-evento, hay t picamente una interfaz receptora de eventos correspondiente. Un receptor de eventos para un evento GUI es un objeto de una clase que implementa uno o m as de las interfaces receptoras de eventos de los paquetes java.awt.event o javax.swing.event. Varios de los tipos receptores de eventos son comunes a componentes Swing y componentes AWT. Tales tipos est an declarados en el paquete java.awt.event, y algunos est an mostrados en la gura 3.2. Los tipos adicionales de receptores de eventos que son espec cos para componentes Swing est an declarados en el paquete javax.swing.event. Cada interfaz receptora de eventos indica uno o m as m etodos de manejo de eventos que deber a ser declarado en la clase que implementa la interfaz. Cualquier clase que implemente una interfaz deber a declarar todos los m etodos abstract de la interfaz; de otra forma, la clase es una clase abstract y no puede ser usada para crear objetos.

3.6.

Como trabaja el manejador de eventos

Se comenta como el mecanismo de manejo de eventos trabaja, usando el ejemplo de la secci on 3.4 para la variable de instancia campoTexto1 de la clase VentanaTextField. 1. C omo fue registrado el manejador de eventos? Mediante el registro de eventos hecho en las l neas 4346 de la apalicaci on. 2. C omo sabe el componente GUI que debe llamar a actionPerformed en vez de otro m etodo manejador? Registrando eventos. Cada JComponent tiene una variable de instancia llamada listenerList que reere a un objeto de la clase EventListenerList del paquete javax.swing.event. Cada objeto de una subclase de JComponent mantiene una referencia a todos sus receptores registrados en la listenerList. Cuando la l nea 43 de la clase VentanaTextField campoTexto1.addActionListener( manejador ); se ejecuta una nueva entrada conteniendo una referencia al objeto manejador que es puesta en la lista listenerList de campoTexto1. Empleando este mecanismo, cada componente GUI ligero mantiene su propia lista de receptores que fueron registrados para manejar los eventos del componente.

52

Componentes GUI

Figura 3.2: Algunas interfaces receptoras de eventos del paquete java.awt.event.

3.7 JButton

53

El tipo del receptor de eventos es importante para que el componente GUI sepa llamar a actionPerformed en vez de otro m etodo. Cada componente GUI soporta varios tipos de eventos, incluyendo eventos del rat on, eventos del teclado y otros. Cuando un evento ocurre, el evento es despachado solamente a los receptores de eventos del tipo apropiado. Despachar es simplemente el proceso por el cual el componente GUI llama un m etodo de manejo de eventos para cada uno de sus receptores que est an registrados para un tipo de evento particular que ocurri o. Cada tipo de evento tiene una o m as interfaces receptoras de eventos correspondientes. Por ejemplo, eventos ActionEvent son manejados por la interfaz ActionListener, eventos MouseEvent son manejados por las interfaces MouseListener y MouseMotionListener, y eventos KeyEvent son manejados por la interfaz KeyListener. Cuando un evento ocurre, el componente GUI recibe (desde la JVM) un ID de evento u nico indicando el tipo de evento. El componente GUI usa el ID para decidir el tipo de receptor al cual el evento deber a ser despachado y para decidir cual m etodo llamar en cada objeto receptor. Para un evento ActionEvent, el evento es despachado para cada m etodo actionPerformed de ActionListener registrado (el u nico m etodo en la interfaz ActionListener).

3.7.

JButton

Un bot on es un componente que el usuario pulsa para lanzar una acci on espec ca. Una aplicaci on de Java puede usar varios tipos de botones, incluyendo botones de pulsaci on o command button, de selecci on o checkbox button, de interruptor o toggle button y de radio radio button. La gura 3.3 muestra la jerarqu a de herencia de los botones revisados en este cap tulo. Como se puede ver, todos los tipos de botones son subclases de AbstractButton del paquete javax.swing, la cual declara las caracter sticas comunes de los botones Swing. Un bot on de pulsaci on genera un evento ActionEvent cuando el usuario pulsa el bot on. Los botones de pulsaci on son creados con la clase JButton. El texto en la cara de un JButton es llamada etiqueta de bot on. Una GUI puede tener varios JButton, pero cada etiqueta de bot on t picamente deber a ser u nica en la porci on de la GUI que es mostrada. La siguiente aplicaci on crea dos JButtons y muestra que los JButton soportan el despliegue de Icons. El manejo de eventos para los botones es

54

Componentes GUI

Figura 3.3: Jerarqu a de los botones Swing. realizado por una sola instancia de la clase interna ManejadorBoton (l neas 3947).
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 // VentanaBoton.java // Creaci on de JButtons. import java.awt.FlowLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JFrame; import javax.swing.JButton; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JOptionPane; public class VentanaBoton extends JFrame { private JButton jBotonPlano; // bot on con solo texto private JButton jBotonAdornado; // bot on con iconos // VentanaBoton agrega JButtons al JFrame public VentanaBoton() { super( "Probando Botones" ); setLayout( new FlowLayout() ); // poner dise~ no de ventana jBotonPlano = new JButton( "Bot on Plano" ); // bot on con texto add( jBotonPlano ); // agregar jBotonPlano a JFrame Icon bug1 = new ImageIcon(getClass().getResource("gnome-gnibbles.png") );

3.7 JButton

55

27 Icon bug2 = new ImageIcon(getClass().getResource("gnome-robots.png")); 28 jBotonAdornado = new JButton( "Bot on Adornado", bug1 ); // poner icon 29 jBotonAdornado.setRolloverIcon( bug2 ); // poner icon rotaci on 30 add( jBotonAdornado ); // agregar jBotonAdornado a JFrame 31 32 // crear nuevo ManejadorBoton para manejar eventos del bot on 33 ManejadorBoton handler = new ManejadorBoton(); 34 jBotonAdornado.addActionListener( handler ); 35 jBotonPlano.addActionListener( handler ); 36 } // fin del constructor VentanaBoton 37 38 // clase interna para el manejo de eventos del bot on 39 private class ManejadorBoton implements ActionListener { 40 41 // manejar evento del bot on 42 public void actionPerformed( ActionEvent event ) { 43 44 JOptionPane.showMessageDialog( VentanaBoton.this, String.format( 45 "Ha presionado: %s", event.getActionCommand() ) ); 46 } // fin del m etodo actionPerformed 47 } // fin de la clase interna privada ManejadorBoton 48 } // fin de la clase VentanaBoton

Las l neas 1415 declaran las variables JButton jBotonPlano y jBotonAdornado. Los correspondientes objetos son instanciados en el constructor. La l nea 23 crea jBotonPlano con la etiqueta de bot on Bot on Plano. La l nea 24 agrega el bot on al JFrame. Un JButton puede desplegar un Icon. Para dar al usuario un nivel extra de interacci on visual con la GUI, un JButton puede tambi en tener un Icon de rotaci onun Icon que es mostrado cuando el usuario pone el rat on sobre el bot on. Las l neas 2627 crean dos objetos ImageIcon que representan el icono por defecto y el de rotaci on para el bot on que es creado en la l nea 28. La l nea 28 crea jBotonAdornado con el texto Bot on Adornado y el icono bug1. Por defecto, el texto es mostrado a la derecha de la imagen. La l nea 29 usa setRolloverIcon, heredada de la clase AbstractButton, para indicar la imagen mostrada en el bot on cuando el usuario posiciona el rat on encima de este. La l nea 30 agrega el bot on al JFrame. Los JButtons, como los JTextFields, generan eventos ActionEvent que pueden ser procesados por cualquier objeto ActionListener. Las l neas 33 35 crean un objeto de la clase private ManejadorBoton y lo registran como el manejador de evento para cada JButton. La clase ManejadorBoton, en las l neas 3947, declara actionPerformed para mostrar un cuadro de di alogo

56

Componentes GUI

conteniendo la etiqueta para el bot on que el usuario presion o. Para un evento JButton, el m etodo getActionCommand regresa la etiqueta sobre el bot on. Cuando se ejecuta la aplicaci on y se pulsa sobre uno de sus botones, se observa que el cuadro de di alogo aparece centrado sobre la ventana de la aplicaci on. Esto ocurre porque la llamada al m etodo showMessageDialog de la clase JOptionPane en las l neas 4445 usa VentanaBoton.this en vez de null como primer argumento. Cuando este argumento no es null, este representa al componente padre que llama al cuadro de di alogo, en este caso la ventana de la aplicaci on es el componente padre, y permite que di alogo est e centrado sobre el componente cuando el di alogo es mostrado. VentanaBoton.this representa la referencia del objeto de la clase de nivel superior VentanaBoton. Cuando la palabra clave this es usada en una clase interna, esta se reere al objeto actual de la clase interna que se esta manipulando. Un m etodo de una clase interna puede usar su objeto this de la clase externa si precede a this con el nombre de la clase externa y un punto, como en VentanaBoton.this en la l nea 44 del c odigo previo. El c odigo que crea y usa un VentanaBoton es similar a los vistos previamente. Se muestra a continuaci on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // PruebaBoton.java // Probando VentanaBoton. import javax.swing.JFrame; public class PruebaBoton { public static void main( String args[] ) { VentanaBoton ventanaBoton = new VentanaBoton(); // crear VentanaBoton ventanaBoton.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaBoton.setSize( 275, 130 ); // fijar tama~ no de la ventana ventanaBoton.setVisible( true ); // mostrar la ventana } // fin de main } // fin de la clase PruebaBoton

3.8.

Botones que mantienen estado

Los componentes GUI de Swing contienen tres tipos de botones de estadoJToggleButton, JCheckbox y JRadioButtonque tienen valores de encendido/apagado o verdadero/falso. Las clases JCheckBox y JRadioButton

3.8 Botones que mantienen estado

57

son subclases de JToggleButton ver gura 3.3. Un JRadioButton es diferente de un JCheckbox ya que normalmente varios JRadioButton son agrupados juntos, y son mutuamente excluyentessolamente uno en el grupo puede ser seleccionado a la vez.

3.8.1.

JCheckBox

La aplicaci on siguiente usa dos objetos JCheckBox para seleccionar el estilo deseado para la fuente del texto mostrado en un JTextField. Cuando se selecciona, se aplica un estilo negrita y el otro un estilo it alica. Si ambos son seleccionados, el estilo de la fuente es negrita e it alica. Cuando la aplicaci on inicialmente se ejecuta, ninguno de los dos JCheckbox est a marcado, es decir, ambos est an en falso, por lo que la fuente es plana.
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 // VentanaCheckBox.java // Creaci on de botones JCheckBox. import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.JCheckBox; public class VentanaCheckBox extends JFrame { private JTextField campoTexto; // muestra texto en fuentes cambiantes private JCheckBox negritaJCheckBox; // para activar/desactivar negrita private JCheckBox italicaJCheckBox; // para activar/desactivar it alica // constructor VentanaCheckBox agrega JCheckBoxes a JFrame public VentanaCheckBox() { super( "Prueba JCheckBox" ); setLayout( new FlowLayout() ); // poner dise~ no ventana // configurar JTextField y su fuente campoTexto = new JTextField( "Observar cambio de estilo de la fuente", campoTexto.setFont( new Font( "Serif", Font.PLAIN, 14 ) ); add( campoTexto ); // agregar campoTexto a JFrame negritaJCheckBox = new JCheckBox( "Negrita" ); // crear negrita italicaJCheckBox = new JCheckBox( "It alica" ); // crear it alica

20 );

58

Componentes GUI

30 add( negritaJCheckBox ); // agregar selecci on negrita a JFrame 31 add( italicaJCheckBox ); // agregar selecci on it alica a JFrame 32 33 // registrar receptores para los JCheckBoxes 34 ManejadorBotonSel manejador = new ManejadorBotonSel(); 35 negritaJCheckBox.addItemListener( manejador ); 36 italicaJCheckBox.addItemListener( manejador ); 37 } // fin del constructor VentanaCheckBox 38 39 // clase privada interna para manejar eventos ItemListener 40 private class ManejadorBotonSel implements ItemListener { 41 42 private int valNegrita = Font.PLAIN; // controla estilo negrita 43 private int valItalica = Font.PLAIN; // controla estilo it alica 44 45 // responder a eventos checkbox 46 public void itemStateChanged( ItemEvent event ) { 47 48 // procesar eventos selecci on negrita 49 if ( event.getSource() == negritaJCheckBox ) 50 valNegrita = 51 negritaJCheckBox.isSelected() ? Font.BOLD : Font.PLAIN; 52 53 // procesar eventos selecci on it alica 54 if ( event.getSource() == italicaJCheckBox ) 55 valItalica = 56 italicaJCheckBox.isSelected() ? Font.ITALIC : Font.PLAIN; 57 58 // poner la fuente del campo de texto 59 campoTexto.setFont( 60 new Font( "Serif", valNegrita + valItalica, 14 ) ); 61 } // fin m etodo itemStateChaged 62 } // fin de la clase privada interna ManejadorBotonSel 63 } // fin de la clase VentanaCheckBox

Despu es de que el JTextField es creado e inicializado en la l nea 24, la l nea 25 usa el m etodo setFont, heredado por JTextField indirectamente de la clase Component, para poner la fuente del JTextField a un nuevo objeto de la clase Font, del paquete java.awt. La nueva fuente es inicializada con Serif, un nombre de fuente gen erica representando a una fuente como Times y que es soportada en todas las plataformas Java, con estilo Font.PLAIN y tama no de 14 puntos. Enseguida, las l neas 2829 crean dos objetos JCheckBox. Las cadenas pasadas al constructor de JCheckBox es la etiqueta del bot on de selecci on que aparece a la derecha por defecto.

3.8 Botones que mantienen estado

59

Cuando el usuario pulsa un JCheckBox, un evento ItemEvent ocurre. Este evento puede ser manejado por un objeto ItemListener, el cual deber a implementar el m etodo itemStateChanged. En el ejemplo, el manejador del evento es realizado por una instancia de la clase privada interna ManejadorBotonSel y registrado con el m etodo addItemListener como el receptor para ambos objetos JCheckBox. Las l neas 4243 declaran variables de instancia para la clase interna ManejadorBotonSel. Estas variables representan el estilo de la fuente para el texto mostrado en el JTextField. Inicialmente ambas son Font.PLAIN para indicar que la fuente no es negrita ni it alica. El m etodo itemStateChanged, l neas 4661, es llamado cuando cuando el usuario pulsa en el JCheckBox de negritas o it alicas. El m etodo usa event.getSource() para determinar cual JCheckBox fue pulsado por el usuario. Si fue negritaJCheckBox, la l nea 51 usa el m etodo isSelected de JCheckBox para determinar si el JCheckBox est a seleccionado. Si el bot on de selecci on est a seleccionado, a la variable local valNegrita se le asigna Font.BOLD; de otra forma, se le asigna Font.PLAIN. Una sentencia similar se ejecuta si el usuario pulsa italicaJCheckBox. Si italicaJCheckBox est a seleccionado, a la variable local valItalica se le asigna Font.ITALICA; de otra forma, se le asigna Font.PLAIN. Las l neas 5960 cambian la fuente del JTextField, usando el mismo nombre de fuente y tama no en puntos. La suma de valNegrita y valItalica representa el nuevo estilo de la fuente del JTextField. Cada una de las constantes de Font representan un valor u nico. Font.PLAIN tiene el valor de 0, por lo tanto si valNegrita y valItalica est an puestas a Font.PLAIN, la fuente tendr a el estilo simple. Si uno de los valores de las variables es Font.BOLD o Font.ITALIC, la fuente ser a negrita o it alica. Si ambas tienen un valor diferente de Font.PLAIN, entonces la fuente ser a negrita e it alica.

Relaci on entre la clase interna y su clase de nivel superior Se puede observar que la clase ManejadorBotonSel usa la variable negritaJCheckBox, l neas 49 y 51, la variable italicaJCheckbox, l neas 54 y 56 y campoTexto a pesas de que estas variables no est an declaradas en la clase interna. Una clase interna tiene una relaci on especial con su clase de nivel superiora la clase interna se le permite acceder directamente todas las variables y m etodos de instancia de la clase de nivel superior. El m etodo itemStateChanged, l neas 4661, de la clase ManejadorBotonSel usa esta relaci on para determinar cual JCheckBox es la fuente del evento, para determinar el estado del JCheckBox

60

Componentes GUI

y para poner la fuente de campoTexto. Se debe observar que ninguna parte del c odigo de la clase interna ManejadorBotonSel requiere una referencia al objeto de la clase de nivel superior. La clase PruebaCheckBox contiene el m etodo principal que ejecuta la aplicaci on VentanaCheckBox.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // PruebaCheckBox.java // Testing VentanaCheckBox. import javax.swing.JFrame; public class PruebaCheckBox { public static void main( String args[] ) { VentanaCheckBox ventanaCheckBox = new VentanaCheckBox(); ventanaCheckBox.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaCheckBox.setSize( 300, 100 ); // poner tama~ no ventana ventanaCheckBox.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase PruebaCheckBox

3.8.2.

JRadioButton

Los botones de radio, declarados con la clase JRadioButton, son similares a los JCheckBox en el sentido de que estos tienen dos estados seleccionado y deseleccionado. Sin embargo, los botones de radio normalmente aparecen como grupo en el cual solamente un bot on puede ser seleccionado a la vez. Seleccionando un bot on de radio diferente fuerza al resto a ser deseleccionados. Los botones de radio son usados para representar opciones mutuamente excluyentes. La relaci on l ogica entre botones de radio es mantenida por un objeto ButtonGroup del paquete javax.swing, el cual por s mismo no es un componente GUI. Un objeto ButtonGroup organiza un grupo de botones y por si mismo no es mostrado en la interfaz del usuario. Sin embargo, los objetos JRadioButton individuales del grupo son mostrados en la GUI. La siguiente aplicaci on es similar a la del ejemplo usando JCheckBox. El usuario puede alterar el estilo de la fuente del JTextField. La aplicaci on usa botones de radio que permiten solamente un estilo individual de fuente, en el grupo para ser seleccionado a la vez.
1 // VentanaRadioButton.java

3.8 Botones que mantienen estado


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 // Creando botones de radio usando ButtonGroup y JRadioButton. import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.JRadioButton; import javax.swing.ButtonGroup; public class VentanaRadioButton extends JFrame { private private private private private private private private private private

61

JTextField campoTexto; // usdo para mostrar los cambios de fuente Font fuentePlana; // fuente para texto plano Font fuenteNegrita; // fuente para texto negrita Font fuenteItalica; // fuente para texto it alica Font fuenteNegritaItalica; // fuente para texto negrita e it alica JRadioButton planoJRadioButton; // selecciona texto plano JRadioButton negritaJRadioButton; // selecciona texto negrita JRadioButton italicaJRadioButton; // selecciona texto it alica JRadioButton negritaItalicaJRadioButton; // negrita e it alica ButtonGroup grupoRadio; // buttongroup para los botones radio

// Constructor VentanaRadioButton que agrega JRadioButtons a JFrame public VentanaRadioButton() { super( "Prueba RadioButton" ); setLayout( new FlowLayout() ); // poner dise~ no ventana campoTexto = new JTextField( "Observar cambio de estilo de la fuente", 25 ); add( campoTexto ); // agregar campoTexto a JFrame // crear botones de radio planoJRadioButton = new JRadioButton( "Plano", true ); negritaJRadioButton = new JRadioButton( "Negrita", false ); italicaJRadioButton = new JRadioButton( "It alica", false ); negritaItalicaJRadioButton = new JRadioButton( "Negrita//It alica", false ); add( planoJRadioButton ); // agregar bot on plano a JFrame add( negritaJRadioButton ); // agregar bot on negrita a JFrame add( italicaJRadioButton ); // agregar bot on it alica a JFrame add( negritaItalicaJRadioButton ); // agregar bot on negrita e it alica // crear relaci on l ogica entre JRadioButtons grupoRadio = new ButtonGroup(); // crear ButtonGroup grupoRadio.add( planoJRadioButton ); // agregar plano al grupo

62

Componentes GUI

47 grupoRadio.add( negritaJRadioButton ); // agregar negrita al grupo 48 grupoRadio.add( italicaJRadioButton ); // agregar it alica al grupo 49 grupoRadio.add( negritaItalicaJRadioButton ); // agregar negrita e it alica 50 51 // crear objetos fuente 52 fuentePlana = new Font( "Serif", Font.PLAIN, 14 ); 53 fuenteNegrita = new Font( "Serif", Font.BOLD, 14 ); 54 fuenteItalica = new Font( "Serif", Font.ITALIC, 14 ); 55 fuenteNegritaItalica = new Font( "Serif", Font.BOLD + Font.ITALIC, 14 ); 56 campoTexto.setFont( fuentePlana ); // poner fuente inicial en plano 57 58 // registrar manejadores de eventos para JRadioButtons 59 planoJRadioButton.addItemListener( 60 new ManejadorRadioButton( fuentePlana ) ); 61 negritaJRadioButton.addItemListener( 62 new ManejadorRadioButton( fuenteNegrita ) ); 63 italicaJRadioButton.addItemListener( 64 new ManejadorRadioButton( fuenteItalica ) ); 65 negritaItalicaJRadioButton.addItemListener( 66 new ManejadorRadioButton( fuenteNegritaItalica ) ); 67 } // fin del constructor VentanaRadioButton 68 69 // clase privada interna para manejar los eventos de los botones de radio 70 private class ManejadorRadioButton implements ItemListener { 71 72 private Font fuente; // fuente asociada con su receptor 73 74 public ManejadorRadioButton( Font f ) { 75 76 fuente = f; // poner la fuente de este receptor 77 } // fin del constructor ManejadorRadioButton 78 79 // manejador de eventos botones de radio 80 public void itemStateChanged( ItemEvent event ) { 81 82 campoTexto.setFont( fuente ); // poner fuente de campoTexto 83 } // fin del m etodo itemStateChanged 84 } // fin de la clase privada ManejadorRadioButton 85 } // fin de la clase VentanaRadioButton

Las l neas 3542 en el constructor crean cuatro objetos JRadioButton y son agregados al JFrame. Cada JRadioButton es creado con una llamada a un constructor como el que est a en la l nea 35. Este constructor indica la etiqueta que aparecer a a la derecha del JRadioButton por defecto y el estado inicial. Un segundo argumento true indica que el JRadioButton deber a aparecer

3.8 Botones que mantienen estado

63

seleccionado cuando este sea mostrado. La l nea 45 instancia un objeto grupoRadio de tipo ButtonGroup. Este objeto es el aglutinador que forma la relaci on l ogica entre los cuatro objetos JRadioButton y permite que solamente uno de los cuatro sea seleccionado a la vez. Es posible que no est e seleccionado alg un JRadioButton en un ButtonGroup, y ocurre cuando no hay ning un JRadioButton preseleccionado y el usuario tampoco ha seleccionado todav a ning un JRadioButton. Las l neas 4649 usan el m etodo add de ButtonGroup para asociar cada uno de los JRadioButton con grupoRadio. Si m as de un objeto JRadioButton seleccionado es agregado al grupo, el primer objeto seleccionado que fue agregado ser a seleccionado cuando la GUI sea mostrada. JRadioButtons, parecidos a los JCheckBoxes, generan eventos ItemEvents cuando son pulsados. Las l neas 5966 crean cuatro instancias de la clase interna ManejadorRadioButton, declarada en las l neas 7084. En el ejemplo, cada objeto receptor de eventos est a registrado para manejar los ItemEvent generados cuando el usuario pulsa un JRadioButton particular. Observar que cada objeto ManejadorRadioButton est a inicializado con un objeto fuente particular creado en las l neas 5255. La clase ManejadorRadioButton, l neas 7084, implementa la interfaz ItemListener por lo que esta clase puede manejar los eventos ItemEvents generados por los JRadioButtons. El constructor guarda el objeto Font que este recibe como un argumento en la variable de instancia del objeto receptor de eventos fuente, declarado en la l nea 72. Cuando el usuario pulsa un JRadioButton, grupoRadio apaga el JRadioButton seleccionado previamente y el m etodo itemStateChanged, lineas 8083, pone la fuente en el JTextField a la fuente guardada correspondiente al objeto receptor de eventos del JRadioButton. En la l nea 82 de la clase interna ManejadorRadioButton usa la variable de instancia campoTexto de la clase de nivel superior para poner la fuente. La clase PruebaRadioButton, que se muestra enseguida, contiene el m etodo main que ejecuta la aplicaci on VentanaRadioButton
1 2 3 4 5 6 7 // PruebaRadioButton.java // Prueba VentanaRadioButton. import javax.swing.JFrame; public class PruebaRadioButton { public static void main( String args[] ) {

64

Componentes GUI

8 9 VentanaRadioButton ventanaRadioButton = new VentanaRadioButton(); 10 ventanaRadioButton.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 11 ventanaRadioButton.setSize( 350, 100 ); // poner tama~ no ventana 12 ventanaRadioButton.setVisible( true ); // mostrar ventana 13 } // fin de main 14 } // fin de la clase PruebaRadioButton

3.9.

JComboBox

Una caja combinada, llamada a veces lista despegable, da una lista de objetos de la cual el usuario puede hacer una sola selecci on. Las cajas combinadas est an implementadas con la clase JComboBox, la cual extiende a JComponent. Un JComboBox genera eventos ItemEvents como un JCheckBox o un JRadioButton. La siguiente aplicaci on usa un JComboBox para dar una lista de cuatro nombres de archivos de los cuales el usuario puede seleccionar la imagen a mostrar. Cuando el usuario selecciona un nombre, la aplicaci on muestra la imagen correspondiente como un Icon en un JLabel.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // VentanaComboBox.java // Usando un JComboBox para seleccionar una imagen a mostrar import java.awt.FlowLayout; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JComboBox; import javax.swing.Icon; import javax.swing.ImageIcon; public class VentanaComboBox extends JFrame { private JComboBox imagenesJComboBox; // para tener los nombres de los ico private JLabel etiqueta; // etiqueta para mostrar icon seleccionado private String nombres[] = {"alacarte.png","distributor-logo.png", "gnome-gnibbles.png","gnome-robots.png"}; private Icon iconos[] = { new ImageIcon( getClass().getResource( nombres[ 0 ] ) ), new ImageIcon( getClass().getResource( nombres[ 1 ] ) ), new ImageIcon( getClass().getResource( nombres[ 2 ] ) ), nos

3.9 JComboBox
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 new ImageIcon( getClass().getResource( nombres[ 3 ] ) ) }; // constructor VentanaComboBox agrega JComboBox a JFrame public VentanaComboBox() { super( "Probando JComboBox" ); setLayout( new FlowLayout() ); // fijar dise~ no de ventana

65

imagenesJComboBox = new JComboBox( nombres ); // configurar JComboBox imagenesJComboBox.setMaximumRowCount( 3 ); // mostrar tres renglones imagenesJComboBox.addItemListener( new ItemListener() { // clase interna an onima // manejo de evento JComboBox public void itemStateChanged( ItemEvent event ) { // determinar si evento es seleccionado if ( event.getStateChange() == ItemEvent.SELECTED ) etiqueta.setIcon( iconos[ imagenesJComboBox.getSelectedIndex() ] ); } // fin del m etodo itemStateChanged } // fin de la clase interna an onima ); // fin de la llamada a addItemListener add( imagenesJComboBox ); // agregar combobox a JFrame etiqueta = new JLabel( iconos[ 0 ] ); // mostrar el primer icono add( etiqueta ); // agregar etiqueta a JFrame } // fin del constructor VentanaComboBox

Usando una clase interna an onima para manejo de eventos. Las l neas 3446 son una sentencia que declara la clase receptora de eventos, crea un objeto de esa clase y registra ese objeto como el receptor para los eventos ItemEvents de imagenesJComboBox. En este ejemplo, el objeto receptor de evento es una instancia de una clase interna an onimauna forma especial de clase interna que est a declarada sin un nombre y que t picamente aparece dentro de la declaraci on de un m etodo. Al igual que con otras clases internas, una clase interna an onima puede acceder los miembros de la clase de nivel superior. Sin embargo, una clase interna an onima tiene acceso limitado a las variables locales del m etodo en donde est a declarada. Como sea una clase an onima, un objeto de esta clase deber a ser creado en el punto donde la clase est a declarada, iniciando en la l nea 35.

66

Componentes GUI

Las l neas 3446 son una llamada al m etodo addItemListener de imagenesJComboBox. El argumento a este m etodo deber a ser un objeto que sea un ItemListener, es decir, cualquier objeto de una clase que implemente ItemListener. Las l neas 3545 son una expresi on clase-creaci on instancia que declara una clase interna an onima y crea un objeto de esa clase. Una referencia a ese objeto es entonces pasada como el argumento a addItemListener. La sintaxis ItemListener() despues de new inicia la declaraci on de una clase interna an onima que implementa la interfaz ItemListener. Los par entesis despu es de ItemListener indican una llamada al constructor por defecto de la clase interna an onima. La clase PruebaComboBox, que se muestra enseguida, contiene el m etodo main que ejecuta la aplicaci on VentanaComboBox descrita previamente.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // PruebaComboBox.java // Probando VentanaComboBox. import javax.swing.JFrame; public class PruebaComboBox { public static void main( String args[] ) { VentanaComboBox ventanaComboBox = new VentanaComboBox(); ventanaComboBox.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaComboBox.setSize( 350, 150 ); // fijar tama~ no de ventana ventanaComboBox.setVisible( true ); // mostrar frame } // fin de main } // fin de la clase

3.10.

JList

Una lista muestra una serie de art culos de los cuales el usuario podr a seleccionar uno o m as de ellos. Las listas son creadas con la clase JList, la cual directamente extiende la clase JComponent. La clase JList soporta listas de selecci on simple, lo que permite que solamente un art culo sea seleccionado a la vez y listas de selecci on m ultiple, las cuales permiten seleccionar cualquier n umero de elementos. La siguiente aplicaci on crea una JList conteniendo 13 nombres de colores. Cuando un nombre de color es pulsado en la JList, un evento ListSelectionEvent ocurre y la aplicaci on cambia el color de fondo de la aplicaci on al color seleccionado.

3.10 JList
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 // VentanaLista.java // Seleccionando colores de un JList. import java.awt.FlowLayout; import java.awt.Color; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionEvent; import javax.swing.ListSelectionModel; public class VentanaLista extends JFrame {

67

private JList colorJList; // lista para mostrar colores private final String nombreColores[] = { "Negro", "Azul", "Cian", "Gris obscuro", "Gris", "Verde", "Gris claro", "Magenta", "Naranja", "Rosa", "Rojo", "Blanco", "Amarillo" }; private final Color colores[] = { Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE, Color.YELLOW }; // constructor VentanaLista agrega JScrollPane conteniendo JList a JFrame public VentanaLista() { super( "Prueba Lista" ); setLayout( new FlowLayout() ); // fijar dise~ no ventana colorJList = new JList( nombreColores ); // crear con nombreColores colorJList.setVisibleRowCount( 5 ); // mostrar cinco renglones a la vez // no permitir selecci on m ultiple colorJList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); // agregar un JScrollPane conteniendo JList al frame add( new JScrollPane( colorJList ) ); colorJList.addListSelectionListener( new ListSelectionListener() { // clase an onima interna // maneja eventos de selecci on de lista public void valueChanged( ListSelectionEvent event ) { getContentPane().setBackground( colores[ colorJList.getSelectedIndex() ] );

68

Componentes GUI

46 } // fin del m etodo valueChanged 47 } // fin de la clase an onima interna 48 ); // fin de la llamada addListSelectionListener 49 } // fin del constructor VentanaLista 50 } // fin de la clase VentanaLista

Diferente a un JComboBox, una JList no proporciona una barra de desplazamiento si hay mas art culos en la lista que el n umero de renglones visibles. En este caso, un objeto JScrollPane es usado para dar la capacidad de desplazar. La l nea 36 agrega una nueva instancia de clase JScrollPane al JFrame. El constructor JScrollPane recibe como su argumento el JComponent que necesita la funci on de desplazamiento, en este caso, colorJList. Por defecto, la barra de desplazamiento aparece solamente cuando el n umero de art culos en el JList excede el n umero de art culos visibles. La clase PruebaLista contiene el m etodo main que ejecuta la aplicaci on VentanaLista.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // PruebaLista.java // Seleccionando colores desde un JList. import javax.swing.JFrame; public class PruebaLista { public static void main( String args[] ) { VentanaLista ventanaLista = new VentanaLista(); // crear VentanaLista ventanaLista.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaLista.setSize( 350, 150 ); // fijar tama~ no ventana ventanaLista.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase PruebaLista

3.11.

Listas de selecci on m ultiple

Una lista de selecci on m ultiple permite al usuario seleccionar varios art culos de un JList. Una lista SINGLE INTERVAL SELECTION permite seleccionar un rango continuo de art culos. Para hacerlo, pulsar en el primer elemento, entonces mantener presionada la tecla cambio mientras se presiona en el u ltimo elemento en el rango. Una lista MULTIPLE INTERVAL SELECTION permite selecci on de rangos continuos como se describi o para una lista SINGLE

3.11 Listas de selecci on m ultiple

69

INTERVAL SELECTION. Tales listas permiten articulos variados para ser seleccionados manteniendo presionada la tecla Ctrl mientras se pulsa sobre cada art culo a seleccionar. Para deseleccionar un art culo, manteniendo presionada la tecla Ctrl mientras se pulsa el art culo una segunda vez. La siguiente aplicaci on usa listas de selecci on m ultiple para copiar art culos de una JList a otra. Una lista es una lista MULTIPLE INTERVAL SELECTION y la otra es una lista SINGLE INTERVAL SELECTION.
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 // VentanaSeleccionMultiple.java // Copiar art culos de una lista a otra. import java.awt.FlowLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JButton; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; public class VentanaSeleccionMultiple extends JFrame { private JList colorJList; // lista para mantener los nombres de los colores private JList copiaJList; // lista para copiar nombres de colores private JButton copiarJButton; // bot on para copiar nombres seleccionados private final String nombreColores[] = { "Negro", "Azul", "Cian", "Gris obscuro", "Gris", "Verde", "Gris claro", "Magenta", "Naranja", "Rosa", "Rojo", "Blanco", "Amarillo" }; // constructor VentanaSeleccionMultiple public VentanaSeleccionMultiple() { super( "Listas de Selecci on M ultiple" ); setLayout( new FlowLayout() ); // fijar dise~ no ventana colorJList = new JList( nombreColores ); // nombres de todos los colores colorJList.setVisibleRowCount( 5 ); // mostrar cinco renglones colorJList.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION ); add( new JScrollPane( colorJList ) ); // agregar lista con scrollpane copiarJButton = new JButton( "Copiar >>>" ); // crear bot on copiar copiarJButton.addActionListener( new ActionListener() { // clase an onima interna

70

Componentes GUI

37 38 // manejar bot on evento 39 public void actionPerformed( ActionEvent event ) { 40 41 // colocar valores seleccionados en copiaJList 42 copiaJList.setListData( colorJList.getSelectedValues() ); 43 } // fin m etodo actionPerformed 44 } // fin de la clase interna an onima 45 ); // fin de la llamada a addActionListener 46 47 add( copiarJButton ); // agregar bot on copiar al JFrame 48 49 copiaJList = new JList(); // crear lista con los nombres copiados 50 copiaJList.setVisibleRowCount( 5 ); // mostrar 5 renglones 51 copiaJList.setFixedCellWidth( 100 ); // fijar ancho 52 copiaJList.setFixedCellHeight( 15 ); // fijar alto 53 copiaJList.setSelectionMode( 54 ListSelectionModel.SINGLE_INTERVAL_SELECTION ); 55 add( new JScrollPane( copiaJList ) ); // agregar lista con scrollpane 56 } // fin del constructor VentanaSeleccionMultiple 57 } // fin de la clase VentanaSeleccionMultiple

En el c odigo anterior, la l nea 27 crea colorJList del tipo JList y lo inicializa con las cadenas en el arreglo nombreColores. La l nea 28 pone el n umero de renglones visibles en colorJList a 5. Las l neas 2930 indican que colorJList es una lista de selecci on de intervalo m ultiple. La l nea 31 agrega un JScrollPane nuevo conteniendo a colorJList a la ventana. Las l neas 4955 realizan tareas similares para copiaJList, la cual es declarada como lista de selecci on de intervalo u nica. La l nea 51 usa el m etodo setFixedCellWidth de JLista para poner el ancho de copiaJList a 100 p xeles. La l nea 52 usa el m etodo setFixedCellHeight de JList para poner el alto de cada art culo en la JList a 15 p xeles. No hay eventos para indicar que el usuario ha hecho selecciones m ultiples en una lista de selecci on m ultiple. Normalmente, un evento generado por otro componente GUI, conocido como un evento externo indica cuando las selecciones m ultiples en una JList deber a ser procesada. En el ejemplo, el usuario pulsa el JButton llamado copiarJButton para lanzar el evento que copia los art culos seleccionados en colorJList a copiaJList. Las l neas 3945 declaran, crean y registran un ActionListener para el copiarJButton. Cuando el usuario pulsa el bot on, el m etodo actionPerformed, l neas 3943, usa el m etodo setListData para poner los art culos mostrados en copiaJList. La l nea 42 llama al m etodo getSelectedValues de

3.12 Manejo de eventos del rat on

71

colorJList, el cual regresa un arreglo de Objects representando los art culos seleccionados en colorJList. En el ejemplo, el arreglo regresado es pasado como argumento al m etodo setListData de copiaJList.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // PruebaSeleccionMultiple.java // Probando VentanaSeleccionMultiple. import javax.swing.JFrame; public class PruebaSeleccionMultiple { public static void main( String args[] ) { VentanaSeleccionMultiple ventanaSeleccionMultiple = new VentanaSeleccionMultiple(); ventanaSeleccionMultiple.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaSeleccionMultiple.setSize( 350, 140 ); // poner tama~ no ventana ventanaSeleccionMultiple.setVisible( true ); // mostrar ventana } // fin main } // fin de la clase PruebaSeleccionMultiple

3.12.

Manejo de eventos del rat on

Se presenta las interfaces MouseListener y MouseMotionListener para manejo de eventos del rat on. Los eventos del rat on pueden ser atrapados por cualquier componente GUI que derive de java.awt.Component. Los m etodos de las interfaz MouseListener se resumen a continuaci on. public void mousePressed( MouseEvent event ) Llamado cuando un bot on del rat on es presionado mientras el apuntador del rat on est a sobre un componente. public void mouseClicked( MouseEvent event ) Llamado cuando un bot on del rat on es presionado y soltado mientras el apuntador del rat on permanece estacionario sobre un componente. Este evento es siempre precedido por una llamada a mousePressed. public void mouseReleased( MouseEvent event ) Llamado cuando un bot on del rat on es soltado despu es de haber sido presionado. Este evento es siempre precedido por una llamada a mousePressed y uno o m as llamadas a mouseDragged.

72

Componentes GUI

public void mouseEntered( MouseEvent event ) Llamado cuando el apuntador del rat on entra en la regi on de un componente. public void mouseExited( MouseEvent event ) Llamado cuando el apuntador del rat on deja la regi on de un componente. Los m etodos de MouseMotionListener se resumen a continuaci on. public void mouseDragged( MouseEvent event ) Llamado cuando el bot on del rat on es presionado mientra el apuntador del rat on est a sobre un componente y el rat on es movido mientras el bot on del rat on se mantiene presionado. Este evento es siempre precedido por una llamado a mousePressed. Todos los eventos de arrastre son mandados al componente en el cual el usuario empez o a arrastrar el rat on. public void mouseMoved( MouseEvent event ) Llamado cuando el rat on es movido cuando el apuntador del cursor est a sobre un componente. Todos los eventos movimiento son mandados al componente sobre el cual el rat on est a posicionado actualmente. El paquete javax.swing.event contiene la interfaz MouseInputListener, la cual extiende las interfaces MouseListener y MouseMotionListener para crear una sola interfaz conteniendo todos los m etodos de estas interfaces. Los m etodos de MouseListener y MouseMotionListener son llamados cuando el rat on interact ua con un componente si los objetos receptores de eventos apropiados est an registrados para ese componente. Cada uno de los m etodos manejadores de eventos del rat on toman un objeto MouseEvent como su argumento. Un objeto MouseEvent contiene informaci on acerca del evento de rat on que ocurri o, incluyendo las coordenadas x e y del lugar donde el evento ocurri o. Estas coordenadas est an medidas desde la esquina superior izquierda del componente GUI en el cual el evento ocurri o. La coordenada x inicia en 0 y se incrementa de izquierda a derecha. La coordenada y inicia en 0 y se incrementa de arriba hacia abajo. Adem as, los m etodos y constantes de la clase InputEvent, la superclase de MouseEvent, permiten a una aplicaci on determinar cual bot on del rat on fue presionado. Java tambi en proporciona la interfaz MouseWheelListener para permitir a las aplicaciones responder a la rotaci on de la rueda del rat on. Esta interfaz declara el m etodo mouseWheelMoved, la cual recibe un evento

3.12 Manejo de eventos del rat on

73

MouseWheelEvent como su argumento. La clase MouseWheelEvent, una subclase de MouseEvent, contiene m etodos que permiten al manejador de eventos obtener informaci on acerca de la cantidad de rotaci on de la rueda. Siguiendo eventos del rat on en un JPanel. La aplicaci on HuellaRaton, que se muestra a continuaci on, prueba los m etodos de las interfaces MouseListener y MouseMotionListener. La aplicaci on implementa ambas interfaces por lo que puede escuchar sus propios eventos de rat on. Observar que todos los m etodos de estas dos interfaces deben ser declarados por el programador cuando una clase implementa ambas interfaces. Cada evento de rat on en este ejemplo muestra una cadena en la JLabel llamada barraEstado en la parte inferior de la ventana.
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 // VentanaHuellaRaton.java // Mostrando eventos del rat on. import java.awt.Color; import java.awt.BorderLayout; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class VentanaHuellaRaton extends JFrame { private JPanel panelRaton; // panel en el cual los eventos del rat on ocur private JLabel barraEstado; // etiqueta que muestra informaci on del event // constructor VentanaHuellaRaton configura la GUI y // registra manejadores de evento de rat on public VentanaHuellaRaton() { super( "Mostrando Eventos de Rat on" ); panelRaton = new JPanel(); // crear panel panelRaton.setBackground( Color.WHITE ); // poner color de fondo add( panelRaton, BorderLayout.CENTER ); // agregar panel al JFrame barraEstado = new JLabel( "Rat on fuera de JPanel" ); add( barraEstado, BorderLayout.SOUTH ); // agregar etiqueta al JFrame // crear y registrar receptores para eventos de rat on y movimiento ren o

74
31 32 33 34 35 36 37 38 39 40 41 42 43 44 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

Componentes GUI
ManejadorRaton manejador = new ManejadorRaton(); panelRaton.addMouseListener( manejador ); panelRaton.addMouseMotionListener( manejador ); } // fin del constructo VentanaHuellaRaton private class ManejadorRaton implements MouseListener, MouseMotionListener { // manejadores de eventos MouseListener // manejar evento cuando el bot on del rat on fue presionado y soltado public void mouseClicked( MouseEvent event ) { barraEstado.setText( String.format( "Pulsado en [%d, %d]", event.getX(), event.getY() ) ); event.getX(), event.getY() ) ); } // fin del m etodo mouseClicked // manejar evento cuando el bot on del rat on fue presionado public void mousePressed( MouseEvent event ) { barraEstado.setText( String.format( "Pressionado en [%d, %d]", event.getX(), event.getY() ) ); } // fin del m etodo mousePressed // manejar evento cuando el bot on del rat on fue soltado despu es de arr public void mouseReleased( MouseEvent event ) { barraEstado.setText( String.format( "Soltado en [%d, %d]", event.getX(), event.getY() ) ); } // fin del m etodo mouseReleased // manejar evento cuando el rat on ingresa al area public void mouseEntered( MouseEvent event ) { barraEstado.setText( String.format( "Rat on entrado en [%d, %d]", event.getX(), event.getY() ) ); panelRaton.setBackground( Color.GREEN ); } // fin del m etodo mouseEntered // manejar evento cuando rat on salga del area public void mouseExited( MouseEvent event ) { barraEstado.setText( "Rat on fuera del JPanel" ); panelRaton.setBackground( Color.WHITE ); } // fin del m etodo mouseExited astrar

3.13 Clases adaptadoras

75

75 76 // manejador de eventos MouseMotionListener 77 // manejar evento cuando el usuario arrastra con boton presionado 78 public void mouseDragged( MouseEvent event ) { 79 80 barraEstado.setText( String.format( "Arrastrado en [%d, %d]", 81 event.getX(), event.getY() ) ); 82 } // fin del m etodo mouseDragged 83 84 // manejar evento cuando el usuario mueve el rat on 85 public void mouseMoved( MouseEvent event ) { 86 barraEstado.setText( String.format( "Movido en [%d, %d]", 87 event.getX(), event.getY() ) ); 88 } // fin del m etodo mouseMoved 89 } // fin de la clase interna ManejadorRaton 90 } // fin de la clase VentanaHuellaRaton

La clase HuellaRaton se usa para crear un objeto del tipo VentanaHuellaRaton.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 // HuellaRaton.java // Probrando VentanaHuellaRaton. import javax.swing.JFrame; public class HuellaRaton { public static void main( String args[] ) { VentanaHuellaRaton VentanaHuellaRaton = new VentanaHuellaRaton(); VentanaHuellaRaton.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); VentanaHuellaRaton.setSize( 350, 200 ); // fijar tama~ no ventana VentanaHuellaRaton.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase HuellaRaton

3.13.

Clases adaptadoras

Varias interfaces receptoras de eventos, como MouseListener y MouseMotionListener, tienen m etodos m ultiples. No siempre es deseable declarar cada m etodo en una interfaz receptora de eventos. Por ejemplo, una aplicaci on podr a solamente necesitar el manejador mouseClicked de MouseListener o el manejador mouseDragged de MouseMotionListener. La interfaz WindowListener especica siete m etodos manejados de eventos. Para varias de las

76

Componentes GUI

interfaces receptoras que tienen m etodos m ultiples, los paquetes java.awt.event y javax.swing.event dan clases adaptadoras receptoras de eventos. Una clase adaptadora implementa una interfaz y da una implementaci on por defecto, con un cuerpo de m etodo vac o, de cada m etodo de la interfaz. Se muestra a continuaci on varias clases adaptadoras de java.awt.event y las interfaces que estas implementan. Se puede extender una clase adaptadora para heredar la implementaci on por defecto de cada m etodo y subsecuentemente sobreescribir solamente los m etodos que se necesiten para manejar eventos. Clase adaptadora ComponentAdapter ContainerAdapter FocusAdapter KeyAdapter MouseAdapter MouseMotionAdapter WindowAdapter Interfaz implementada ComponentListener ContainerListener FocusListener KeyListener MouseListener MouseMotionListener WindowListener

Extendiendo MouseAdapter. La siguiente aplicaci on muestra como determinar el n umero de pulsaciones y como distinguir entre los diferentes botones del rat on. El receptor de eventos en la aplicaci on es un objeto de la clase interna ManejadorPulsacionesRaton, en las l neas 2646 que extiende a MouseAdapter, con lo que s olo se requiere declarar el m etodo mouseClicked que se necesita en el ejemplo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // VentanaDetallesRaton.java // Mostrando pulsaciones del rat on y distinguiendo entre sus botones import java.awt.BorderLayout; import java.awt.Graphics; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JLabel; public class VentanaDetallesRaton extends JFrame { private String detalles; // cadena representante private JLabel barraEstado; // JLabel aparece en la parte inferior de la // constructor configura cadena de barra de t tulos y registra receptor

ventana

3.13 Clases adaptadoras

77

16 public VentanaDetallesRaton() { 17 18 super( "Pulsaciones rat on y botones" ); 19 20 barraEstado = new JLabel( "Pulsar el rat on" ); 21 add( barraEstado, BorderLayout.SOUTH ); 22 addMouseListener( new ManejadorPulsacionesRaton() ); // agregar maneja 23 } // fin del constructor VentanaDetallesRaton 24 25 // clase interna para manejar eventos del rat on 26 private class ManejadorPulsacionesRaton extends MouseAdapter { 27 28 // manejar evento pulsaci on y determinar cual bot on se presion o 29 public void mouseClicked( MouseEvent event ) { 30 31 int posX = event.getX(); // obtener la posici on x del rat on 32 int posY = event.getY(); // obtener la posici on y del rat on 33 34 detalles = String.format( "Pulsado %d ve%s", 35 event.getClickCount(), event.getClickCount()==1?"z":"ces"); 36 37 if ( event.isMetaDown() ) // bot on derecho del rat on 38 detalles += " con bot on derecho del rat on"; 39 else if ( event.isAltDown() ) // bot on central del rat on 40 detalles += " con bot on central del rat on"; 41 else // bot on izquierdo del rat on 42 detalles += " con bot on izquierdo del rat on"; 43 44 barraEstado.setText( detalles ); // mostrar mensaje en barraEstado 45 } // fin del m etodo mouseClicked 46 } // fin de la clase privada interna ManejadorPulsacionesRaton 47 } // fin de la clase VentanaDetallesRaton

dor

Un usuario de una aplicaci on de Java podr a estar en un sistema con un rat on de uno, dos o tres botones. Java proporciona un mecanismo para distinguir entre los botones del rat on. La clase MouseEvent hereda varios m etodos de la clase InputEvent que pueden distinguir los botones del rat on en un rat on multibot on o un rat on que pueda simular uno multibot on con una combinaci on de tecla y de pulsaci on del rat on. La siguiente tabla muestra los m etodos InputEvent usados para distinguir entre las pulsaciones del raton. Java asume que cada rat on contiene un bot on izquierdo. En el caso de un rat on de uno o dos botones, la aplicaci on de Java supone que el bot on central del rat on es pulsado si el usuario mantiene presionada la tecla Alt y pulsa el

78

Componentes GUI

bot on izquierdo en un rat on de dos botones o el u nico bot on en un rat on con un s olo bot on. En el caso de un rat on de un bot on, una aplicaci on de Java supone que el bot on derecho es pulsado si el usuario mantiene presionada la tecla Meta y pulsa el bot on del rat on. M etodo isMetaDown() Descripci on Regresa true cuando el usuario pulsa el bot on derecho en un rat on con dos o tres botones. Para simular la pulsaci on con el bot on derecho en un rat on de un bot on, el usuario deber a mantener presionada la tecla Meta y pulsar el bot on del rat on. Regresa true cuando el usuario pulsa el bot on central en un rat on con tres tres botones. Para simular la pulsaci on con el bot on central en un rat on con uno o dos botones, el usuario puede presionar la tecla Alt del teclado y pulsar el u nico bot on o el bot on izquierdo, respectivamente.

isAltDown()

1 2 3 4 5 6 7 8 9 10 11 12 13 14

// DetallesRaton.java // Probando VentanaDetallesRaton. import javax.swing.JFrame; public class DetallesRaton { public static void main( String args[] ) { VentanaDetallesRaton ventanaDetallesRaton = new VentanaDetallesRaton() ventanaDetallesRaton.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaDetallesRaton.setSize( 400, 150 ); // fijar tama~ no ventana lventanaDetallesRaton.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase DetallesRaton ;

3.14.

Subclase JPanel para dibujar con el rat on

En la secci on 3.12 se muestra como seguir los eventos del rat on en un JPanel. En esta secci on, se usa un JPanel como una area dedicada de dibujo en la cual el usuario puede dibujar arrastrando el rat on. Adem as,

3.14 Subclase JPanel para dibujar con el rat on

79

en esta secci on se muestra un receptor de eventos que extiende una clase adaptadora. El m etodo paintComponent Los componentes ligeros de Swing que extienden la clase JComponent, como JPanel, contienen al m etodo paintComponent, el cual es llamado cuando un componente es mostrado. Sobreescribiendo este m etodo, se puede indicar como dibujar guras usando las capacidades gr acas de Java. Cuando se congura un JPanel para usarlo como una area dedicada de dibujo, la subclase deber a sobreescribir el m etodo paintComponent y llamar la versi on de la superclase de paintComponent como la primera sentencia en el cuerpo del m etodo para asegurar que el componente se muestra correctamente. La raz on para esto es que la subclases de JComponent soportan transparencia. Para mostrar un componente correctamente, el programa debe determinar si el componente es transparente. El c odigo que lo determina est a en la implementaci on paintComponent de la superclase JComponent. Cuando un componente es transparente, paintComponent no limpiar a su fondo cuando el programa muestre el componente. Cuando un componente es opaco, paintComponent limpia el fondo del componente antes de que el componente sea mostrado. Si la versi on de la superclase de paintComponent no es llamado, un componente opaco GUI no ser a mostrado correctamente en la interfaz del usuario. Tambi en, si la versi on de la superclase es llamada despu es de hacer las sentencias de dibujado conguradas, los resultados t picamente ser an borrados. La transparencia de un componente ligero de Swing puede ser puesta con el m etodo setOpaque, un argumento false indica que el componente es transparente. Deniendo la conguraci on del area de dibujado La aplicaci on Pintar, que se est a enseguida, muestra una subclase congurada de JPanel que es usada para crear una area dedicada de dibujo. La aplicaci on usa el manejo de evento mouseDragged para crear una aplicaci on simple de dibujo. El usuario puede dibujar arrastrando el rat on sobre el JPanel. El ejemplo no usa el m etodo mouseMoved, por lo que la clase receptora de eventos, la clase interna an onima en las l neas 2234, extiende MouseMotionAdapter. Como esta clase ya declara a mouseMoved y mouseDragged, simplemente se sobreescribe mouseDragged para dar el manejo de evento que requiere la aplicaci on.
1 // PintaPanel.java 2 // Usando la clase MouseMotionAdapter.

80
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 import import import import import java.awt.Point; java.awt.Graphics; java.awt.event.MouseEvent; java.awt.event.MouseMotionAdapter; javax.swing.JPanel;

Componentes GUI

public class PintaPanel extends JPanel { private int cuentaPuntos = 0; // contar n umero de puntos // arreglo de 10000 referencias java.awt.Point private Point puntos[] = new Point[ 10000 ]; // configurar la GUI y registrar el manejador de eventos del rat on public PintaPanel() { // manejar el evento del moviemiento del rat on en la ventana addMouseMotionListener( new MouseMotionAdapter() { // clase an onima interna // guardar las coordenadas del arrastre y repintar public void mouseDragged( MouseEvent event ) { if ( cuentaPuntos < puntos.length ) { puntos[ cuentaPuntos ] = event.getPoint(); // asignar punto cuentaPuntos++; // incrementar el contador repaint(); // repintar JFrame } // fin if } // fin m etodo mouseDragged } // fin de la clase interna an onima ); // fin de la llamada a addMouseMotionListener } // fin del constructor PintaPanel // dibujar elipses en caja contenedora de 4x4 en la posici on dada en la ventana public void paintComponent( Graphics g ) { super.paintComponent( g ); // limpiar el area de dibujado // dibujar todos los puntos del arreglo for ( int i = 0; i < cuentaPuntos; i++ ) g.fillOval( puntos[ i ].x, puntos[ i ].y, 4, 4 ); } // fin del m etodo paintComponent } // fin de la clase PintaPanel

3.14 Subclase JPanel para dibujar con el rat on

81

La clase PintaPanel, que se muestra a continuaci on, extiende a JPanel para crear el a rea dedicada de dibujo. Las l neas 37 importan las clases usadas en la clase PaintPanel. La clase Point del paquete java.awt representa un coordenada x y . Se usan objetos de esta clase para guardar las coordenadas de cada evento arrastrar. La clase Graphics es usada para dibujar. En este ejemplo, se usa un arreglo de 10,000 puntos, l nea 14, para guardar la localidad en la cual el evento de arrastrar el rat on ocurre. Como se ver a, el m etodo paintComponent usa estos puntos para dibujar. La variable de instancia cuentaPuntos, l nea 11, mantiene el n umero total de puntos capturados de los eventos de arrastre hasta el momento. Las l neas 2035 registra un evento MouseMotionListener para escuchar los eventos de movimiento del rat on de PintarPanel. Las l neas 2234 crean un objeto de una clase interna an onima que extiende la clase adaptadora MouseMotionAdapter. Se recuerda que MouseMotionAdapter implementa MouseMotionListener, por lo que el objeto de la clase interna es un MouseMotionListener. La clase interna an onima hereda una implementaci on por defecto de los m etodos mouseMoved y mouseDragged, por lo que ya satisface los requerimientos de que todos los m etodos de la interfaz deban ser implementados. Sin embargo, los m etodos por defecto no hacen nada cuando son llamados. Por lo tanto, se sobreescribe el m etodo mouseDragged en las l neas 2533 para capturar las coordenadas de un evento de arrastre y se guardan como un objeto Point. La l nea 27 asegura que se guarden las coordenadas del evento solamente si todav a hay espacio en el arreglo. Si hay, en la l nea 29 se llama al m etodo getPoint de MouseEvent para obtener el punto donde el evento ocurri o y guardarlo en el arreglo en el ndice cuentaPuntos. La l nea 30 incrementa cuentaPuntos, y la l nea 31 llama al m etodo repaint, heredado indirectamente de la clase Component para indicar que el PintaPanel debe ra ser refrescado en la pantalla tan pronto como sea posible con una llamada al m etodo painComponent de PintaPanel. El m etodo paintComponent, l neas 3946, el cual recibe un par ametro Graphics, es llamado autom aticamente en cualquier momento que PaintPanel necesite ser mostrado en la pantalla, como cuando la GUI es mostrada por primera vez o refrescada en la pantalla, como cuando el m etodo repaint es llamado o cuando el componente GUI fue ocultado por otra ventana en la pantalla y subsecuentemente se hace visible nuevamente.
1 // Pintar.java

82
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Probando PintaPanel. import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JLabel; public class Pintar { public static void main( String args[] ) {

Componentes GUI

// crear JFrame JFrame application = new JFrame( "Un programa simple de pintado" ); PintaPanel pintaPanel = new PintaPanel(); // crear panel de pintado application.add( pintaPanel, BorderLayout.CENTER ); // in center // crear una etiqueta y colocarla en la parte SOUTH del BorderLayout application.add( new JLabel( "Arrastrar el rat on para dibujar" ), BorderLayout.SOUTH ); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.setSize( 400, 200 ); // fijar tama~ no de ventana application.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase Pintar

3.15.

Manejo de eventos del teclado

Se presenta la interfaz KeyListener para manejar eventos del teclado. Los eventos del teclado son generados cuando las teclas del teclado son presionadas y soltadas. Una clase que implementa KeyListener deber a dar declaraciones para los m etodos keyPressed, keyReleased y keyTyped, cada uno de los cuales recibe un KeyEvent como su argumento. La clase KeyEvent es una subclase de InputEvent. El m etodo keyPressed es llamado como respuesta al presionar alguna tecla. El m etodo keyTyped es llamado como respuesta al presionar cualquier tecla que no sea una tecla de acci on. Las teclas de acci on son Inicio, Fin, ReP ag, AvP ag, Bloq Num, Despl, Pausa, Inter, Despl, Imp Pnt, Bloq May, teclas de funci on y teclas de navegaci on del cursor de texto. El m etodo keyReleased es llamado cuando la tecla es soltada despu es de cualquier evento keyPressed o keyTyped. La siguiente aplicaci on muestra los m etodos de KeyListener. La clase VentanaDemoTecla implementa la interfaz KeyListener, por lo tanto los

3.15 Manejo de eventos del teclado tres m etodos est an declarados en la aplicaci on.
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 // VentanaDemoTecla.java // Mostrando eventos de teclazos. import java.awt.Color; import java.awt.event.KeyListener; import java.awt.event.KeyEvent; import javax.swing.JFrame; import javax.swing.JTextArea;

83

public class VentanaDemoTecla extends JFrame implements KeyListener { private private private private String linea1 = ""; // primera l nea del area de texto String linea2 = ""; // segunda l nea del area de texto String linea3 = ""; // tercera l nea del area de texto JTextArea areaTexto; // area de texto para mostrar la salida

// constructor VentanaDemoTecla public VentanaDemoTecla() { super( "Mostrando eventos de teclazos" ); areaTexto = new JTextArea( 10, 15 ); // configurar JTextArea areaTexto.setText( "Presionar cualquier tecla del teclado..." ); areaTexto.setEnabled( false ); // deshabilitar el areaTexto areaTexto.setDisabledTextColor( Color.BLACK ); // poner color del texto add( areaTexto ); // agregar areaTexto al JFrame addKeyListener( this ); // permitir a la ventana procesar los eventos de teclas } // fin del constructor VentanaDemoTecla // manejar tecla presionada public void keyPressed( KeyEvent event ) { linea1 = String.format( "Tecla presionada: %s", event.getKeyText( event.getKeyCode() ) ); // salida de tecla presionada setLineas2y3( event ); // poner l neas de salida 2 y 3 } // fin del m etodo keyPressed // manejar tecla soltada public void keyReleased( KeyEvent event ) { linea1 = String.format( "Tecla soltada: %s", event.getKeyText( event.getKeyCode() ) ); // salida de tecla soltada setLineas2y3( event ); // poner l neas de salida 2 y 3 } // fin del m etodo keyReleased

84

Componentes GUI

45 46 // manejar tecla acci on presionada 47 public void keyTyped( KeyEvent event ) { 48 49 linea1 = String.format( "Tecla tecleada: %s", event.getKeyChar() ); 50 setLineas2y3( event ); // poner l neas de salida 2 y 3 51 } // fin del m etodo keyTyped 52 53 // poner segunda y tercera l nea de salida 54 private void setLineas2y3( KeyEvent event ) { 55 56 linea2 = String.format( "Esta tecla %ses una tecla acci on", 57 ( event.isActionKey() ? "" : "no " ) ); 58 59 String temp = event.getKeyModifiersText( event.getModifiers() ); 60 61 linea3 = String.format( "Teclas modificadoras presionadas: %s", 62 ( temp.equals( "" ) ? "none" : temp ) ); // modificadores de salida 63 64 areaTexto.setText( String.format( "%s\n%s\n%s\n", 65 linea1, linea2, linea3 ) ); // salida tres l neas de texto 66 } // fin del m etodo setLineas2y3 67 } // fin de la clase VentanaDemoTecla 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // DemoTecla.java // Probando VentanaDemoTecla. import javax.swing.JFrame; public class DemoTecla { public static void main( String args[] ) { VentanaDemoTecla ventanaDemoTecla = new VentanaDemoTecla(); ventanaDemoTecla.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaDemoTecla.setSize( 350, 100 ); // fijar tama~ no de la ventana ventanaDemoTecla.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase DemoTecla

El constructor, l neas 1728, registra la aplicaci on para manejar sus propios eventos del teclado usando el m etodo addKeyListener en la l nea 27. El m etodo addKeyListener est a declarado en la clase Component, por lo tanto cada subclase de Component puede noticar objetos KeyListener de eventos del teclado para ese componente.

3.16 Manejadores de dise no

85

En la l nea 25, el constructor agrega areaTexto del tipo JTextArea al JFrame, donde la salida de la aplicaci on es mostrada. Observar en la pantalla que areaTexto ocupa la ventana entera. Esto es debido a que el manejado por defecto del JFrame es BorderLayour. Cuando un s olo componente es agregado a un BorderLayout, el componente ocupa el contenedor entero. En la l nea 24 se usa el m etodo setDisabledTextColor para cambiar el color del texto en el area de texto a negro. El m etodo keyPressed, l neas 3160 y el m etodo keyReleased, l neas 3944 usan el m etodo getKeyCode de la clase KeyEvent para obtener el c odigo virtual de la tecla de la tecla que fue presionada. La clase KeyEvent mantiene un conjunto de constanteslas constantes del c odigo virtual de teclasque representan cada tecla sobre el teclado. Estas constantes pueden ser comparadas con el valor regresado por getKeyCode para probar teclas individuales. El valor regresado por getKeyCode es pasado al m etodo getKeyText de KeyEvent, el cual regresa una cadena conteniendo el nombre de la tecla que fue presionada. Para una lista completa de las constantes del c odigo virtual de teclas, revisar la documentaci on para la clase KeyEvent. El m etodo keyTyped, l neas 4751, usa el m etodo getKeyChar de KeyEvent para obtener el valor Unicode del caracter tecleado. Los tres m etodos manejadores de evento terminan llamando al m etodo setLineas2y3, l neas 5466, y pas andole el objeto KeyEvent. Este m etodo usa isActionKey de KeyEvent para determinar si la tecla en el evento fue una tecla acci on. Tambi en, el m etodo getModifiers de InputEvent es llamado, l nea 59, para determinar si alg un modicador de teclas, tales como Cambio, Alt y Ctrl, fueron presionadas cuando el evento tecla ocurri o. El resultado de ese m etodo es pasado al m etodo getKeyModifiersText de KeyEvent, el cual produce una cadena conteniendo los nombres de las teclas modicadoras presionadas.

3.16.

Manejadores de dise no

Los manejadores de dise no son proporcionados para poner en orden los componentes GUI en un contenedor para prop ositos de presentaci on. Los programadores puede usar los manejadores para capacidades de dise no b asico en vez de determinar la posici on exacta y tama no de cada componente GUI. Esta funcionalidad permite al programador concentrarse en la apariencia y comportamiento b asico y dejar al manejador de dise no el proceso de varios

86

Componentes GUI

detalles del dise no. Todos los manejadores de dise no implementan la interfaz LayoutManager del paquete java.awt. El m etodo setLayout de la clase Container toma un objeto que implementa la interfaz LayoutManager como un argumento. Hay b asicamente tres formas para arreglar los componentes en una GUI:

1. Posicionamiento absoluto: este propociona el mayor nivel de control sobre la apariencia de la GUI. Poniendo el manejador de un Container a null, se puede indicar la posici on absoluta de cada componente GUI con respecto a la esquina superior izquierda del contenedor. Si se hace esto, se debe especicar de cada componente GUI su tama no. Programar una GUI con posicionamiento absoluto puede ser tedioso, a menos que se tenga un ambiente integrado de desarrollo o IDE (Integrated Devolpment Environment ) que pueda generar el c odigo por el programador.

2. Manejador de dise no: usando manejadores de dise no para colocar elementos puede ser m as simple y r apido que crear una GUI con posicionamiento absoluto, pero se pierde alg un control sobre el tama no y el posicionamiento preciso de los componentes GUI.

3. Programaci on visual en una IDE: las IDEs dan herramientas que hacen f acil la creaci on de GUIs. Cada IDE t picamente da una herramienta de dise no GUI que permite arrastrar y soltar componentes GUI desde una caja de herramientas en una a rea de dise no. Se puede entonces los componentes posicionarlos, alinearlos y darles el tama no requerido de acuerdo con el programador. La IDE genera el c odigo Java que crea la GUI. Adem as, se puede t picamente agregar c odigo de manejo de eventos para un componente particular haciendo doble pulsaci on sobre el componente.

En la siguiente tabla se resumen los manejadores de dise no presentados en este cap tulo.

3.16 Manejadores de dise no Manejador FlowLayout Descripci on Por defecto para javax.swing.JPanel. Coloca los componentes secuencialmente, de izquierda a derecha en el orden en que fueron agregados. Tambi en es posible indicar el orden de los componentes usando el m etodo add de Container, el cual toma un componente y una posici on de ndice entero como argumentos. Por defecto para JFrame y otras ventanas. Coloca los componentes en una de cinco a reas: NORTH, SOUTH, EAST, WEST y CENTER. Arregla los componentes en renglones y columnas.

87

BorderLayout

GridLayout

3.16.1.

FlowLayout

FlowLayout es el manejador de dise no m as simple. Los componentes GUI son colocados en un contenedor de izquierda a derecha conforme al orden en el cual fueron agregados al contenedor. Cuando una orilla del contenedor es alcanzada, los componentes contin uan mostr andose en la siguiente l nea. La clase FlowLayout permite a los componentes GUI estar alineados a la izquierda, al centro (por defecto) y a la derecha. La siguiente aplicaci on crea tres objetos JButton y los agrega a la aplicaci on, usando un manejador de dise no FlowLayout. Los componentes son alineados al centro por defecto. Cuando el usuario pulsa Izquierda, la alineaci on para el manejador de dise no cambia a la izquierda en el FlowLayout. Los otros dos botones alinean los componentes como se indica en la etiqueta del bot on. Cada boton tiene su propio manejador de evento que est a declarado con una clase interna que implementa ActionListener. Un manejador de contenedor es puesto con el m etodo setLayot de la clase Container. La l nea 25 pone el manejador de dise no FlowLayout declarado en la l nea 23. Normalmente, el manejador es puesto antes que cualquier componente GUI sea agregado al contenedor. Cada manejador de evento de bot on est a especicado con una objeto de una clase interna an onima, l neas 3043, 4861 y 6671. Cada actionPerformed de los manejadores de evento de los botones ejecuta dos sentencias.

88

Componentes GUI

Por ejemplo, la l nea 37 en el m etodo actionPerformed para el bot on izquierdo usa el m etodo setAlignment para cambiar a la izquierda la alineaci on en el FlowLayout usando FlowLayout.LEFT. La l nea 40 usa el m etodo layoutContainer de la interfaz LayoutManager, que es heredado por todos los manejadores para indicar que el JFrame deber a ser rearreglado de acuerdo al ajuste del manejador.
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 // VentanaFlowLayout.java // Mostrando las alineaciones de FlowLayout. import java.awt.FlowLayout; import java.awt.Container; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JFrame; import javax.swing.JButton; public class VentanaFlowLayout extends JFrame { private private private private private JButton botonIzq; // bot on para alinear a la izquierda JButton botonCentr; // bot on para alinear al centro JButton botonDer; // bot on para alinear a la derecha FlowLayout manejador; // objeto manejador Container contenedor; // contenedor para poner manejador

// configurar la GUI y registrar los receptores para los botones public VentanaFlowLayout() { super( "Demo FlowLayout" ); manejador = new FlowLayout(); // crear FlowLayout contenedor = getContentPane(); // obtener contenedor para el manejador setLayout( manejador ); // poner manejador para la ventana // configurar botonIzq y registrar receptor botonIzq = new JButton( "Izquierda" ); // crear bot on izquierda add( botonIzq ); // agregar bot on izquierda a la ventana botonIzq.addActionListener( new ActionListener() { // clase interna an onima // procesar evento botonIzq public void actionPerformed( ActionEvent event ) { manejador.setAlignment( FlowLayout.LEFT );

3.16 Manejadores de dise no


39 // realinear componentes adjuntos 40 manejador.layoutContainer( contenedor ); 41 } // fin del m etodo actionPerformed 42 } // fin de la clase interna an onima 43 ); // fin de la llamada addActionListener 44 45 // configurar botonCentr y registrar receptor 46 botonCentr = new JButton( "Centro" ); // crear bot on central 47 add( botonCentr ); // agregar bot on central a la ventana 48 botonCentr.addActionListener( 49 50 new ActionListener() { // clase interna an onima 51 52 // procesar evento botonCentr 53 public void actionPerformed( ActionEvent event ) { 54 55 manejador.setAlignment( FlowLayout.CENTER ); 56 // realinear componentes adjuntos 57 manejador.layoutContainer( contenedor ); 58 } // fin del m etodo actionPerformed 59 } // fin de la clase interna an onima 60 ); // fin de la llamada addActionListener 61 62 // configurar botonDer y registrar receptor 63 botonDer = new JButton( "Derecha" ); // crear bot on derecha 64 add( botonDer ); // agregar boton derecha a la ventana 65 botonDer.addActionListener( 66 67 new ActionListener() { // clase interna an onima 68 69 // procesar evento botonDer 70 public void actionPerformed( ActionEvent event ) { 71 72 manejador.setAlignment( FlowLayout.RIGHT ); 73 // realinear componentes adjuntos 74 manejador.layoutContainer( contenedor ); 75 } // fin del m etodo actionPerformed 76 } // fin clase interna an onima 77 ); // fin de la llamada addActionListener 78 } // fin del constructo VentanaFlowLayout 79 } // fin de la clase VentanaFlowLayout 1 // DemoFlowLayout.java 2 // Probando VentanaFlowLayout. 3 import javax.swing.JFrame; 4

89

90

Componentes GUI

5 public class DemoFlowLayout { 6 7 public static void main( String args[] ) { 8 9 VentanaFlowLayout ventanaFlowLayout = new VentanaFlowLayout(); 10 ventanaFlowLayout.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 11 ventanaFlowLayout.setSize( 300, 75 ); // poner tama~ no de la ventana 12 ventanaFlowLayout.setVisible( true ); // mostrar ventana 13 } // fin de main 14 } // fin de la clase DemoFlowLayout

3.16.2.

BorderLayout

El manejador de dise no BorderLayout, el manejador por defecto para un JFrame, arregla los componentes en cinco regiones: NORTH, SOUTH, EAST, WEST y CENTER. NORTH corresponde a la parte superior del contenedor. La clase BorderLayout extiende a Objecto e implementa la interfaz LayoutManager2, una subinterfaz de LayoutManager que agrega varios m etodos para mejorar el procesamiento de dise no. Un BorderLayout limita un Contenedor para tener a lo m as cinco componentesuno en cada regi on. El componente colocado en cada regi on puede ser un contenedor al cual est en otros componentes adjuntados. Los componentes colocados en las regiones NORTH y SOUTH se extienden horizontalmente a los lados del contenedor y son tan altos como los componentes colocados en esas regiones. Las regiones EAST y WEST se expanden verticalmente entre las regiones NORTH y SOUTH y son tan anchos como los componentes colocados en esas regiones. El componente colocado en la regi on CENTER se expande para ocupar todo el espacio restante en el dise no. Si las cinco regiones est an ocupadas, el espacio entero del contenedor est a cubierto por componentes GUI. Si la regi on NORTH y SOUTH no est an ocupadas, los componentes GUI en las regiones EAST, CENTER y WEST se expanden verticalmente para ocupar el espacio restante. Si las regiones EAST y WEST no est an ocupadas, el componente GUI en la regi on CENTER se expande horizontalmente para llenar el espacio restante. Si la regi on CENTER no est a ocupada, el area se deja vac a los otros componentes GUI no se expanden para llenar el espacio restante. La siguiente aplicaci on muestra el manejador de dise no BorderLayout usando cinco JButtons.
1 // VentanaBorderLayout.java 2 // Mostrando BorderLayout.

3.16 Manejadores de dise no


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 import import import import import java.awt.BorderLayout; java.awt.event.ActionListener; java.awt.event.ActionEvent; javax.swing.JFrame; javax.swing.JButton;

91

public class VentanaBorderLayout extends JFrame implements ActionListener { private JButton botones[]; // arreglo de botones para ocultar porciones private final String nombres[] = { "Ocultar Norte", "Ocultar Sur", "Ocultar Este", "Ocultar Oeste", "Ocultar Centro" }; private BorderLayout manejador; // objeto borderlayout // configurar GUI y manejadores de eventos public VentanaBorderLayout() { super( "Demo BorderLayout" ); manejador = new BorderLayout( 5, 5 ); // 5 p xeles de abertura setLayout( manejador ); // poner manejador a la ventana botones = new JButton[ nombres.length ]; // crear arreglo de botones // crear JButtons y registrar receptores para ellos for ( int cont = 0; cont < nombres.length; cont++ ) { botones[ cont ] = new JButton( nombres[ cont ] ); botones[ cont ].addActionListener( this ); } // fin for add( botones[ 0 ], BorderLayout.NORTH ); // agregar bot on al norte add( botones[ 1 ], BorderLayout.SOUTH ); // agregar bot on al sur add( botones[ 2 ], BorderLayout.EAST ); // agregar bot on al este add( botones[ 3 ], BorderLayout.WEST ); // agregar bot on al oeste add( botones[ 4 ], BorderLayout.CENTER ); // agregar bot on al centro } // fin del constructor VentanaBorderLayout // manejador de eventos del rat on public void actionPerformed( ActionEvent event ) { // revisar la fuente del evento y disponer panel correspondiente for ( JButton boton : botones ) { if ( event.getSource() == boton ) boton.setVisible( false ); // ocultar el bot on pulsado else

92

Componentes GUI

48 boton.setVisible( true ); // mostrar los otros botones 49 } // fin for 50 51 manejador.layoutContainer( getContentPane() ); // recalcular el contenido del cuad 52 } // fin del m etodo actionPerformed 53 } // fin de la clase VentanaBorderLayout 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // DemoBorderLayout.java // Probando VentanaBorderLayout. import javax.swing.JFrame; public class DemoBorderLayout { public static void main( String args[] ) { VentanaBorderLayout ventanaBorderLayout = new VentanaBorderLayout(); ventanaBorderLayout.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaBorderLayout.setSize( 300, 200 ); // fijar tama~ no de la ventana ventanaBorderLayout.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase DemoBorderLayout

La l nea 21 de la clase VentanaBorderLayout crea un BorderLayout. Los argumentos del constructor indican el n umero de p xeles entre los componentes que son arreglados horizontalmente (espacio de abertura horizontal) y entre los componentes que son arreglados verticalmente (espacio de abertura vertical), respectivamente. El valor por defecto es un pixel de espacio de abertura horizontal y vertical. La l nea 22 usa el m etodo setLayout para poner el manejador de dise no del panel. Se agregan los componentes a un BorderLayout con otra versi on del m etodo add de la clase Container que toma dos argumentosel componente a agregar y la regi on en la cual el componente debe aparecer. Por ejemplo, la l nea 32 indica que botones[0] deber a aparecer en la regi on NORTH. Los componentes pueden ser agregados en cualquier orden, pero solamente un componente deber a ser agregado a cada regi on. Cuando no se indica la regi on donde ser a agregado el componente a un BorderLayout, el manejador supone que deber a ser puesto en la regi on CENTER. Cuando m as de un componente es agreagado a una regi on, solamente el u ltimo componente agregado ser a mostrado. La clase VentanaBorderLayout implementa ActionListener directamente en este ejemplo, por lo que la VentanaBorderLayout manejar a los eventos

3.16 Manejadores de dise no

93

de los JButtons. Por esta raz on, la l nea 29 pasa la referencia this al m etodo addActionListener de cada JButton. Cuando el usuario pulsa un JButton particular en el dise no, el m etodo actionPerformed, l neas 4052, se ejecuta. La sentencia for mejorada en las l neas 4349 usa un if...else para ocultar el JButton particular que gener o el evento. El m etodo setVisible, heredado en JButton desde la clase Component, es llamado con un argumento false, l nea 46 para ocultar el JButton. Si el JButton actual en el arreglo no es el que genero el evento, el metodo setVisible es llamado con el argumento true, l nea 48, para asegurar que el JButton es mostrado en la pantalla. La l nea 51 usa el m etodo layoutContainer de LayoutManager para recalcular el dise no del contenido del cuadro. Con lo anterior ciertas regiones en el BorderLayout cambian de forma conforme los JButtons son ocultados y mostrados en otras regiones. Para dise nos m as complejos, agrupar los componentes en JPanels, cada uno con su propio manejador de dise no. Colocar los JPanels en el JFrame usando el BorderLayout por defecto o alg un otro dise no.

3.16.3.

GridLayout

El manejador de dise no GridLayout divide el contenedor en una cuadr cula por lo que los componentes pueden ser colocados en renglones y columnas. La clase GridLayout hereda directamente de la clase Object e implementa la interfaz LayoutManager. Cada componente en un GridLayout tiene el mismo ancho y alto. Los componentes son agregados a un GridLayout iniciando en la celda de la esquina superior izquierda de la cuadr cula y procediendo de izquierda a derecha hasta que el rengl on queda lleno. Entonces el proceso continua de izquierda a derecha en el siguiente rengl on de la cuadr cula, y as sucesivamente. La siguiente aplicaci on muestra el manejador de dise no GridLayout usando seis JButtons.
1 2 3 4 5 6 7 8 9 10 // VentanaGridLayout.java // Mostrando GridLayout. import java.awt.GridLayout; import java.awt.Container; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JFrame; import javax.swing.JButton; public class VentanaGridLayout extends JFrame implements ActionListener {

94

Componentes GUI

11 12 private JButton botones[]; // arreglo de botones 13 private final String nombres[] = 14 { "uno", "dos", "tres", "cuatro", "cinco", "seis" }; 15 private boolean conmutador = true; // conmutador entre dos dise~ nos 16 private Container contenedor; // contenedor de la ventana 17 private GridLayout gridLayout1; // primer gridlayout 18 private GridLayout gridLayout2; // segundo gridlayout 19 20 // constructor sin argumentos 21 public VentanaGridLayout() { 22 23 super( "Demo GridLayout" ); 24 gridLayout1 = new GridLayout( 2, 3, 5, 5 ); // 2 x 3; espaciado de 5 25 gridLayout2 = new GridLayout( 3, 2 ); // 3 x 2; sin espaciado 26 contenedor = getContentPane(); // obtener contenido del cuadro 27 setLayout( gridLayout1 ); // poner el dise~ no al JFrame 28 botones = new JButton[ nombres.length ]; // crear arreglo de JButtons 29 30 for ( int contador = 0; contador < nombres.length; contador++ ) { 31 32 botones[ contador ] = new JButton( nombres[ contador ] ); 33 botones[ contador ].addActionListener( this ); // registrar receptor 34 add( botones[ contador ] ); // agregar bot on al JFrame 35 } // fin for 36 } // fin del constructor VentanaGridLayout 37 38 // manejar los eventos del bot on cambiando entre dise~ nos 39 public void actionPerformed( ActionEvent event ) { 40 41 if ( conmutador ) 42 contenedor.setLayout( gridLayout2 ); // poner 2 dise~ no 43 else 44 contenedor.setLayout( gridLayout1 ); // poner 1er dise~ no 45 46 conmutador = !conmutador; // poner conmutador a valor opuesto 47 contenedor.validate(); // redise~ nar contenedor 48 } // fin del m etodo actionPerformed 49 } // fin de la clase VentanaGridLayout 1 2 3 4 5 6 // DemoGridLayout.java // Probando VentanaGridLayout import javax.swing.JFrame; public class DemoGridLayout {

3.17 Paneles anidados

95

7 public static void main( String args[] ) { 8 9 VentanaGridLayout ventanaGridLayout = new VentanaGridLayout(); 10 ventanaGridLayout.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 11 ventanaGridLayout.setSize( 300, 200 ); // fijar tama~ no ventana 12 ventanaGridLayout.setVisible( true ); // mostrar ventana 13 } // fin del main 14 } // fin de la clase DemoGridLayout

3.17.

Usando paneles para manejo de dise nos m as complejos

Para GUIs m as complejos se requiere que cada componente sea colocado en una localidad exacta. Estos consisten de paneles m ultiples, con cada componente del panel arreglado en dise no espec co. La clase JPanel extiende a JComponent y JComponent extiende la clase Container, por lo que cada JPanel es un contenedor. Por lo tanto, cada JPanel podr a tener varios componentes, incluyendo otros paneles, adjuntados a este con el m etodo add de Container. La siguiente aplicaci on muestra como un JPanel puede ser usado para crear un dise no m as complejo en el cual varios JButtons son colocados en la regi on SOUTH de un BorderLayout. Despu es de que el panelBotones tipo JPanel es declarado en la l nea 11 y creado en la l nea 19, la l nea 20 pone el dise no del panelBotones a un GridLayout de un rengl on y cinco columnas. Las l neas 2327 agregan los cinco JButtons del arreglo botones al JPanel en el ciclo. La l nea 26 agrega los botones directamente al JPanella clase JPanel no tiene un cuadro de contenido, como un JFrame. La l nea 29 usa el BorderLayout por defecto para agregar el panelBotones a la regi on SOUTH. La regi on SOUTH es tan alta como los botones en panelBotones. Un JPanel es dimensionado a los componentes que este contiene. Conforme m as componentes sean agregados, el JPanel crece, de acuerdo a las restricciones de su manejador de dise no, para acomodar los componentes.
1 2 3 4 5 6 // VentanaPanel.java // Usando un JPanel para ayudar al dise~ no de los componentes import java.awt.GridLayout; import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JPanel;

96

Componentes GUI

7 import javax.swing.JButton; 8 9 public class VentanaPanel extends JFrame { 10 11 private JPanel buttonJPanel; // panel que contendr a los botones 12 private JButton botones[]; // arreglo de botones 13 14 // constructor sin argumentos 15 public VentanaPanel() { 16 17 super( "Demo Panel" ); 18 botones = new JButton[ 5 ]; // crear arreglo de botones 19 buttonJPanel = new JPanel(); // crear panel 20 buttonJPanel.setLayout( new GridLayout( 1, botones.length ) ); 21 22 // crear y agregar botones 23 for ( int contador = 0; contador < botones.length; contador++ ) { 24 25 botones[ contador ] = new JButton( "Bot on " + ( contador + 1 ) ); 26 buttonJPanel.add( botones[ contador ] ); // agregar bot on al panel 27 } // fin del for 28 29 add( buttonJPanel, BorderLayout.SOUTH ); // add panel to JFrame 30 } // fin del constructor VentanaPanel 31 } // fin de la clase VentanaPanel

1 2 3 4 5 6 7 8 9 10 11 12 13 14

// DemoPanel.java // Probando VentanaPanel. import javax.swing.JFrame; public class DemoPanel extends JFrame { public static void main( String args[] ) { VentanaPanel ventanaPanel = new VentanaPanel(); ventanaPanel.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaPanel.setSize( 450, 200 ); // fijar tama~ no de la ventana ventanaPanel.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase DemoPanel

3.18 JTextArea

97

3.18.

JTextArea

Un JTextArea da una a rea para manipular m ultiples l neas de texto. Como en la clase JTextField, JTextArea es una subclase de JTextComponent, la cual declara m etodos comunes para JTextField y JTextArea y varios otros componentes GUI basados en texto. La siguiente aplicaci on muestra varios componentes JTextArea. Un JTextArea muestra texto que el usuario puede seleccionar. El otro JTextArea es no editable y es usado para mostrar el texto que el usario seleccion o en el primer JTextArea. Al igual que con las JLists de selecci on m ultiple, secci on 3.10, un evento externo de otro componente GUI indica cuando se procesa el texto en el JTextArea. Por ejemplo, cuando se teclea un correo electr onico, normalmente se pulsa un bot on Enviar para mandar el texto del mensaje al receptor. Similarmente, cuando se edita un documento en procesador de palabras, normalmente se guarda el archivo seleccionando la opci on Guardar o Guardar como .... En este programa, el bot on Copia )))) genera el evento externo que copia el texto seleccionado en el JTextArea de la izquierda y lo muestra en el de la derecha.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // VentanaTextArea.java // Copiando texto seleccionado de una area de texto a otra. import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.Box; import javax.swing.JFrame; import javax.swing.JTextArea; import javax.swing.JButton; import javax.swing.JScrollPane; public class VentanaTextArea extends JFrame { private JTextArea textArea1; // mostrar texto demo private JTextArea textArea2; // texto seleccionado es copiado aqu private JButton jButtonCopiar; // inicia el copiado del texto // constructor sin argumentos public VentanaTextArea() { super( "Demo de TextArea" ); Box caja = Box.createHorizontalBox(); // crear caja String demo = "Esta es una cadena demo\n" + "para mostrar el copiado de\ntexto de una area de texto a\n" +

98

Componentes GUI

24 "otra area de texto usando\nun evento externo.\n"; 25 26 textArea1 = new JTextArea( demo, 10, 15 ); // crear textarea1 27 caja.add( new JScrollPane( textArea1 ) ); // agregar scrollpane 28 29 jButtonCopiar = new JButton( "Copiar ))))" ); // crear bot on copiar 30 caja.add( jButtonCopiar ); // agregar bot on copiar a la caja 31 jButtonCopiar.addActionListener( 32 33 new ActionListener() { // clase an onima interna 34 35 // poner texto en textArea2 seleccionado en textArea1 36 public void actionPerformed( ActionEvent event ) { 37 38 textArea2.setText( textArea1.getSelectedText() ); 39 } // fin del m etodo actionPerformed 40 } // fin de la clase an onima interna 41 ); // fin de la llamada a addActionListener 42 43 textArea2 = new JTextArea( 10, 15 ); // crear segundo JTextarea 44 textArea2.setEditable( false ); // deshabilitar edici on 45 caja.add( new JScrollPane( textArea2 ) ); // agregar scrollpane 46 47 add( caja ); // agregar caja a la ventana 48 } // fin del constructor VentanaTextArea 49 } // fin de la clase VentanaTextArea 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // DemoTextArea.java // Copiando texto seleccionado de una area de texto a otra. import javax.swing.JFrame; public class DemoTextArea { public static void main( String args[] ) { VentanaTextArea ventanaTextArea = new VentanaTextArea(); ventanaTextArea.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaTextArea.setSize( 500, 200 ); // fijar tama~ no de la ventana ventanaTextArea.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase DemoTextArea

En el constructor, l neas 1848 de la clase VentanaTextArea, en la l nea 21 se crea un contenedor Box del paquete javax.swing para organizar los componentes GUI. Box es una subclase de Container que usa un manejador

3.19 Ejercicios

99

de dise no BoxLayout para arreglar los componentes GUI ya sea horizontalmente o verticalmente. El m etodo est atico createHorizontalBox de Box crea una caja que arregla los componentes de izquierda a derecha en el orden en el que fueron agregados. Las l neas 26 y 43 crean los JTextArea textArea1 y textArea2. La l nea 26 usa el constructor de tres argumentos de JTextArea, el cual toma una cadena que representa el texto inicial y dos enteros indicando que el JTextArea tiene 10 renglones y 15 columnas. La l nea 43 un constructor de dos argumentos de JTextArea, indicando que el JTextArea tiene 10 renglones y 15 columnas. La l nea 26 indica que demo deber a ser mostrado como el contenido por defecto del JTextArea. Un JTextArea no proporciona barras de desplazamiento si no puede mostrar su contenido completo. Por lo tanto, la l nea 27 crea un objeto JScrollPane, lo inicializa con textArea1 y lo agrega al contenedor caja. Por defecto, las barras de desplazamiento horizontal y vertical aparecer an cuando sean necesarias en un JScrollPane. Las l neas 2941 crean un objeto JButton jButtonCopiar con la etiqueta Copiar )))), lo agregan al contenedor caja y le registran un manejador de eventos para ActionEvent. Este bot on proporciona el evento externo que determina cuando el programa deber a copiar el texto seleccionado en textArea1 a textArea2. Cuando el usuario pulsa jButtonCopiar, la l nea 38 en actionPerformed indica que el m etodo getSelectedText, heredado en JTextArea desde JTextComponent, deber a regresar el texto seleccionado de textArea1. El usuario selecciona texto arrastrando el rat on sobre el texto deseado para resaltarlo. El m etodo setText cambia el texto en textArea2 con la cadena que es regresada por getSelectedText. Las l neas 4345 crean textArea2, ponen su propiedad editable a false y lo agregan al contenedor caja. La l nea 47 agrega caja al JFrame.

3.19.

Ejercicios

1. Dise nar la siguiente calculadora y darle la funcionalidad requerida. Los botones para escoger el estilo del cuadro de texto deber an ser del tipo JCheckBox y los botones para seleccionar el tama no de la fuente del cuadro de texto ser an tipo JRadioButton.

100

Componentes GUI

2. Para el ejemplo en donde se usa una subclase JPanel para dibujar con el raton en la secci on 3.14, agregar las siguientes opciones: a ) Pintar con diferentes colores. b ) Tama no variable de la brocha. c ) Usar diferentes tipos de guras, como rect angulos, l neas verticales, l neas horizontales o elipses. d ) Figuras rellenas o huecas.

3.20.

Usando Men us con Frames

Los men us son una parte integral de las GUIs. Los men us permiten al usuario realizar acciones sin necesidad de saturar una GUI con componentes extras. Los men us simplican las GUIs porque los componentes pueden estar escondidos dentro de ellos. Estos componentes ser an visibles solamente cuando el usuario los busque seleccionando el men u. En las GUI Swing, los men us s olo pueden ser adjuntados a objetos de las clases que dan el m etodo setJMenuBar. Tales clase son JFrame y JApplet. Las clases usadas para declarar men us son JMenuBar, JMenu, JMenuItem, JCheckBoxMenuItem y JRadioButtonMenuItem. La clase JMenuBar, una subclase de JComponent, contiene los m etodos necesarios para manejar una barra de men us, la cual es un contenedor para men us. La clase JMenu, una subclase de javax.swing.JMenuItem, contiene los m etodos necesarios para manejar men us. Los men us contienen elementos men u y son agregados a las barras de men us o a otros men us como submen us. Cuando un men u es pulsado, este se expande para mostrar su lista de elementos men u. La clase JMenuItem, una subclase de javax.swing.AbstractButton, contiene los m etodos necesarios para manejar elementos men u. Un elemento

3.20 Usando Men us con Frames

101

men u es un componente GUI dentro de un men u que, cuando es seleccionado, causa un evento acci on. Un elemento men u puede ser usado para iniciar una acci on, o este puede ser un submen u que proporcione m as elementos men u que el usuario puede seleccionar. Los submen us son u tiles para agrupar elementos men u relacionados en un men u. La clase JCheckBoxMenuItem, una subclase de javax.swing.JMenuItem, contiene los m etodos necesarios para manejar elementos men u que pueden ser activar o desactivar. Cuando un JCheckBoxMenuItem es seleccionado, una marca aparece a la izquierda del elemento men u. Cuando el JCheckBoxMenuItem es seleccionado nuevamente, la marca es removida. La clase JRadioButtonMenuItem, una subclase de javax.swing.JMenuItem contiene los m etodos necesarios para manejar elementos men u que pueden ser activados o desactivados, parecido a JCheckBoxMenuItem. Cuando m ultiples JRadioButtonMenuItem son mantenidos como para de un ButtonGroup, solamente un elemento en el grupo puede ser seleccionado, un c rculo relleno aparece a la izquierda del elemento men u. Cuando otro JRadioButtonMenuItem es seleccionado, el c rculo relleno del men u item seleccionado es removido. La siguiente aplicaci on muestra varios elementos men u y como especicar los caracteres especiales llamados mnem onicos que pueden proporcionar acceso r apido a un men u o un elemento men u desde el teclado. Los mnem onicos pueden ser usados con todas las subclases javax.swing.AbstractButton. La clase VentanaMenu declara los componentes GUI y el manejo de eventos para los elementos men u. La mayor a del c odigo en esta aplicaci on aparece en el constructor de la clase (l neas 34-151).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // VentanaMenu.java // Usando men us. import java.awt.Color; import java.awt.Font; import java.awt.BorderLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import javax.swing.JFrame; import javax.swing.JRadioButtonMenuItem; import javax.swing.JCheckBoxMenuItem; import javax.swing.JOptionPane; import javax.swing.JLabel; import javax.swing.SwingConstants; import javax.swing.ButtonGroup;

102
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 58 59 60 61 import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JMenuBar; public class VentanaMenu extends JFrame {

Componentes GUI

private final Color valoresColor[] = { Color.BLACK, Color.BLUE, Color.RED, Color.GREEN }; private JRadioButtonMenuItem elemsColor[]; // elementos men u color private JRadioButtonMenuItem fuentes[]; // elementos men u fuente private JCheckBoxMenuItem elemsEstilo[]; // elementos men u estilo de fuente private JLabel mostrarJLabel; // muestra texto ejemplo private ButtonGroup grupoBotonFuente; // maneja elementos men u fuente private ButtonGroup grupoBotonColor; // manenja elementos men u color private int estilo; // usada para crear estilos para fuentes // constructor sin argumentos para configurar GUI public VentanaMenu() { super( "Usando JMenus" ); JMenu menuArch = new JMenu( "Archivo" ); // crear men u archivo menuArch.setMnemonic( A ); // poner mnem onico a A // crear elemento menu Acerca de ... JMenuItem elemAcerca = new JMenuItem( "Acerca de ..." ); elemAcerca.setMnemonic( C ); // poner mnem onico a c menuArch.add( elemAcerca ); // agregar elemento acerca al men u archivo elemAcerca.addActionListener( new ActionListener() { // clase interna an onima

// mostrar mensaje de di alogo cuando el usuario selecciona Acerca de ... public void actionPerformed( ActionEvent evento ) { JOptionPane.showMessageDialog( VentanaMenu.this, "Este es un ejemplo\ndel uso de men us.", "Acerca de", JOptionPane.PLAIN_MESSAGE ); } // fin del m etodo actionPerformed } // fin de la clase an onima interna ); // fin de la llamada a addActionListener JMenuItem elemSalir = new JMenuItem( "Salir" ); // crear elemento salir elemSalir.setMnemonic( s ); // poner mnem onico a s menuArch.add( elemSalir ); // agregar elemento salir al men u archivo

3.20 Usando Men us con Frames


62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 elemSalir.addActionListener( new ActionListener() { // clase an onima interna

103

// terminar la aplicaci on cuando el usuario pulse elemSalir public void actionPerformed( ActionEvent evento ) { System.exit( 0 ); // exit application } // fin del m etodo actionPerformed } // fin de la clase an onima interna ); // fin de la llamada a addActionListener JMenuBar barra = new JMenuBar(); // crear barra de men us setJMenuBar( barra ); // agregar barra de men us a la la aplicaci on barra.add( menuArch ); // agregar men u archivo a la barra de men us JMenu menuFormato = new JMenu( "Formato" ); // crear men u formato menuFormato.setMnemonic( F ); // poner mnem onico a F // arreglo listando las cadenas de colores String colores[] = { "Negro", "Azul", "Rojo", "Verde" }; JMenu menuColor = new JMenu( "Color" ); // crear men u color menuColor.setMnemonic( C ); // poner mnem onico a C // crear arreglo para elementos men u botones de radio para colores elemsColor = new JRadioButtonMenuItem[ colores.length ]; grupoBotonColor = new ButtonGroup(); // manejar colores ManejadorElemento manejadorElemento = new ManejadorElemento(); // manejador para colores // crear elementos men u botones de radio for ( int contador = 0; contador < colores.length; contador++ ) { elemsColor[ contador ] = new JRadioButtonMenuItem( colores[ contador ] ); // crear elemento menuColor.add( elemsColor[ contador ] ); // agregar elemento al men u color grupoBotonColor.add( elemsColor[ contador ] ); // agregar al grupo elemsColor[ contador ].addActionListener( manejadorElemento ); } // fin del for elemsColor[ 0 ].setSelected( true ); // marcar el primer elemento menuFormato.add( menuColor ); // agregar men u color al men u formato menuFormato.addSeparator(); // agregar separador en el men u

104
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

Componentes GUI
// arreglo listando los nombres de las fuentes String nombresFuentes[] = { "Serif", "Monospaced", "SansSerif" }; JMenu menuFuente = new JMenu( "Fuente" ); // crear men u fuente menuFuente.setMnemonic( u ); // poner mnem onico a u // crear elementos men u botones de radio para las fuentes fuentes = new JRadioButtonMenuItem[ nombresFuentes.length ]; grupoBotonFuente = new ButtonGroup(); // maneja nombres de fuentes // crear elementos men u fuente bot on de radio for ( int contador = 0; contador < fuentes.length; contador++ ) { fuentes[ contador ] = new JRadioButtonMenuItem( nombresFuentes[ contador ] ); menuFuente.add( fuentes[ contador ] ); // agregar fuente al men u fuente grupoBotonFuente.add( fuentes[ contador ] ); // agregar al grupo fuentes[ contador ].addActionListener( manejadorElemento ); // add handler } // fin for fuentes[ 0 ].setSelected( true ); // seleccionar primer elemento del men u fuente menuFuente.addSeparator(); // agrear separador al men u fuente String nombresEstilos[] = { "Negrita", "It alica" }; // nombres de estilos elemsEstilo = new JCheckBoxMenuItem[ nombresEstilos.length ]; ManejadorEstilo manejadorEstilo = new ManejadorEstilo(); // manejador de estilos // crear elementos men u estilo tipo verificaci on for ( int contador = 0; contador < nombresEstilos.length; contador++ ) { elemsEstilo[ contador ] = new JCheckBoxMenuItem( nombresEstilos[ contador ] ); // crear elemento menuFuente.add( elemsEstilo[ contador ] ); // agregar al men u fuente elemsEstilo[ contador ].addItemListener( manejadorEstilo ); // manejador } // fin del for menuFormato.add( menuFuente ); // agregar men u fuente al men u formato barra.add( menuFormato ); // agregar men u Formato a la barra de men us // configurar etiqueta que mostrar a el texto mostrarJLabel = new JLabel( "Texto Ejemplo", SwingConstants.CENTER ); mostrarJLabel.setForeground( valoresColor[ 0 ] ); mostrarJLabel.setFont( new Font( nombresFuentes[ 0 ], Font.PLAIN, 72 ) ); getContentPane().setBackground( Color.CYAN ); // fijar fondo add( mostrarJLabel, BorderLayout.CENTER ); // agregar mostrarJLabel } // fin del constructor VentanaMenu

3.20 Usando Men us con Frames


152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

105

// clase interna para manejar los eventos acci on de los elementos men u. private class ManejadorElemento implements ActionListener { // procesar selecciones color y fuente public void actionPerformed( ActionEvent evento ) { // procesar selecci on de color for ( int contador = 0; contador < elemsColor.length; contador++ ) { if ( elemsColor[ contador ].isSelected() ) { mostrarJLabel.setForeground( valoresColor[ contador ] ); break; } // fin del if } // fin del for // procesar selecci on de fuente for ( int contador = 0; contador < fuentes.length; contador++ ) { if ( evento.getSource() == fuentes[ contador ] ) { mostrarJLabel.setFont( new Font( fuentes[ contador ].getText(), estilo, 72 ) ); } // fin del if } // fin del for repaint(); // redibujar la aplicaci on } // fin del m etodo actionPerformed } // fin de la clase ManejadorElemento // clase interna para manejar los eventos de los elementos men u verificaci on private class ManejadorEstilo implements ItemListener { // procesar selecciones estilo de fuente public void itemStateChanged( ItemEvent e ) { estilo = 0; // inicializar estilo // revisar por selecci on negrita if ( elemsEstilo[ 0 ].isSelected() ) estilo += Font.BOLD; // agregar negrita a estilo // revisar por selecci on it alica if ( elemsEstilo[ 1 ].isSelected() )

106

Componentes GUI

197 estilo += Font.ITALIC; // agregar it alica a estilo 198 199 mostrarJLabel.setFont( 200 new Font( mostrarJLabel.getFont().getName(), estilo, 72 ) ); 201 repaint(); // redibujar aplicaci on 202 } // fin del m etodo itemStateChanged 203 } // fin de la clase ManejadorEstilo 204 } // fin de la clase VentanaMenu

Las l neas 3876 conguran el men u Archivo y lo adjuntan a la barra de men us. El men u Archivo contiene el elemento men u Acerca de ... que muestra un mensaje de di alogo cuando el elemento men u es seleccionado y el elemento men u Salir puede ser seleccionado para terminar la aplicaci on. La l nea 38 crea un JMenu y pasa al constructor la cadena Archivo como el nombre del men u. La l nea 39 usa de JMenu el m etodo setMnemonic para indicar que A es el mnem onico para este men u. Presionando la tecla Alt y la letra A se abre el men u, como si se hubiese pulsado con el rat on en el nombre del men u. En la GUI, el car acter mnem onico en el nombre del men u es mostrado subrayado. Las l neas 4243 crean el elemAcerca del tipo JMenuItem con el texto Acerca de ... y pone su mnem onico a la letra c. Este elemento men u es agregado a menuArch en la l nea 44 con el m etodo add de JMenu. Las l neas 47 56 crean un ActionListener para procesar los eventos acci on de elemAcerca. Las l neas 52-54 muestran un mensaje cuadro de di alogo. En los primeros usos de showMessageDialog, el primer argumento era null. El prop osito del primer argumento es para especicar la ventana padre que ayuda a determinar donde el cuadro de di alogo ser a desplegado. Si la ventana padre es indicada como null, el cuadro de di alogo aparece en el centro de la ventana. De otra forma, este aparece centrado sobre la ventana padre especicada. En este ejemplo, el programa indica la ventana padre con VentanaMenu.thisla referencia this del objeto VentanaMenu. Cuando se usa la referencia this en una clase interna, indicando this se reere al objeto de la clase interna. Para referir al objeto this de la clase exterior, calicar this con el nombre de la clase exterior y un punto (.). Los cuadros de di alogo son t picamente modales. Un cuadro de di alogo modal no permite que ninguna otra aplicaci on en la ventana sea accedida hasta que el cuadro de di alogo sea descartado. Los cuadros de di alogo mostrados con la clase JOptionPane son di alogos modales. La clase JDialog puede ser usada para crear di alogos modales o no modales.

3.20 Usando Men us con Frames

107

Las l neas 5972 crean el elemento men u elemSalir, ponen su mnem onico a S, lo agregan a menuArch y registran un ActionListener que termina la aplicaci on cuando el usuario selecciona elemSalir. Las l neas 7476 crean un JMenuBar, la adjuntan a la ventana aplicaci on con el m etodo setJMenuBar de JFrame y usan el m etodo add de JMenuBar para adjuntar menuArch al JMenuBar. Las l neas 7879 crean el men u menuFormato y ponen su mnem onico a F. Las l neas 8485 crean el men u menuColor, que ser a un submen u del men u Formato y pone su mnem onico a C. La l nea 88 crea el arreglo elemsColor del tipo JRadioButtonMenuItem, el cual se reere a los elementos men u en menuColor. La l nea 89 crea grupoBotonColor tipo ButtonGroup, el cual asegurar a que solamente uno de los elementos men u en el submen u Color est e seleccionado a la vez. La l nea 90 crea una instancia de la clase interna ManejadorElemento, declarada en las l neas 154181, que responde a selecciones de los submen us Color o Fuente. La sentencia for en las l neas 93100 crea cada JRadioButtonMenuItem del arreglo elemsColor, agrega cada elemento men u a menuColor y a grupoBotonColor y registra el ActionListener para cada elemento men u. La l nea 102 invoca al m etodo setSelected para seleccionar el primer elemento en el arreglo elemsColor. La l nea 104 agrega menuColor como un submen u de menuFormato. La l nea 105 invoca al m etodo addSeparator de AbstractButton para agregar un l nea separadora horizontal al men u. Las l neas 108126 crean el submen u Fuente y varios JRadioButtonMenuItem y seleccionan el primer elemento del arreglo fuentes de tipo JRadioButtonMenuItem. La l nea 129 crea un arreglo JCheckBoxMenuItem para representar los elementos men u para indicar los estilos negrita e it alica para las fuentes. La l nea 130 crea una instancia de la clase interna ManejadorEstilo, declarada en las l neas 184203, para responder a los eventos JCheckBoxMenuItem. La sentencia for en las l neas 133139 crea cada JCheckBoxMenuItem, agrega cada elemento men u a menuFuente y registra el ItemListener para cada elemento men u. La l nea 141 agrega menuFuente como un submen u de menuFormato. La l nea 142 agrega el menuFormato a la barra de men us. Las l neas 145147 crean un JLabel del que se controla la fuente, el color y el estilo con los elementos men u del men u Formato. El color inicial de la fuente es puesto con el primer elemento del arreglo valoresColor invocando al m etodo setForeground de JComponent, y la fuente incial es puesta a Serif con estilo PLAIN y de 72 puntos de tama no. La l nea 148 pone el color de fondo del contenido de la ventana a cian, y la l nea 150 agrega el JLabel

108

Componentes GUI

al centro de la ventana. El m etodo actionPerformed de ManejadorElemento en las l neas 157 180, usa dos sentencia for para determinar cual elemento men u fuente o color gener o el evento y poner la fuente o color de mostrarJLabel. La condici on if en la l nea 162 usa el m etodo isSelected de AbstractButton para determinar el JRadioButtonMenuItem seleccionado. La condici on if en la l nea 172 invoca al m etodo getSource del objeto evento para obtener una referencia al JRadioButtonMenuItem que gener o el evento. La l nea 175 invoca al m etodo getText de AbstractButton para obtener el nombre de la fuente del elemento men u. El programa llama al m etodo itemStateChanged de ManejadorEstilo, l neas 187202, si el usuario selecciona un JCheckBoxMenuItem en el menuFuente. Las l neas 192 y 196 determinan cual de los dos JCheckBoxMenuItems est an seleccionados y usan sus estados combinados para determinar el nuevo estilo de la fuente.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // PruebaMenu.java // Usando VentanaMenu. import javax.swing.JFrame; public class PruebaMenu { public static void main( String args[] ) { VentanaMenu ventanaMenu = new VentanaMenu(); // crear VentanaMenu ventanaMenu.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaMenu.setSize( 600, 200 ); // fijar tama~ no de la ventana ventanaMenu.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase PruebaMenu

3.21.

JPopupMenu

Varias de las aplicaciones para computadoras actuales proporcionan los men us emergentes sensitivos al contexto. En Swing, tales men us son creados con la clase JPopupMenu, una subclase de JComponent. Estos men us proporcionan opciones que son espec cas al componente que gener o el evento disparador emergente. En varios sistemas, el evento disparador emergente ocurre cuando el usuario presiona y suelta el bot on derecho del rat on.

3.21 JPopupMenu

109

La aplicaci on de esta secci on crea un JPopupMenu que permite al usuario seleccionar uno de tres colores para cambiar el color del fondo de la ventana. Cuando el usuario pulsa el bot on derecho del rat on sobre el fondo de la ventana PruebaPopup, un JPopupMenu conteniendo colores aparece. Si el usuario pulsa un JRadioButtonMenuItem para un color, el m etodo actionPerformed de ManejadorElemento cambia el color del fondo del panel de la ventana.
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 // VentanaPopup.java // Mostrando JPopupMenus. import java.awt.Color; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JFrame; import javax.swing.JRadioButtonMenuItem; import javax.swing.JPopupMenu; import javax.swing.ButtonGroup; public class VentanaPopup extends JFrame {

private JRadioButtonMenuItem elems[]; // mantiene elementos para colores private final Color colores[] = { Color.BLUE, Color.YELLOW, Color.RED }; // colores que ser an usados private JPopupMenu men uEmergente; // permite al usuario seleccionar color // constructor sin argumentos para configurar GUI public VentanaPopup() { super( "Usando JPopupMenus" ); ManejadorElemento manejador = new ManejadorElemento(); // manejador para men u elems String nombColores[] = {"Azul","Amarillo","Rojo" }; // arreglo de nombres de Colores ButtonGroup colorGroup = new ButtonGroup(); // maneja los elementos color menuEmergente = new JPopupMenu(); // crear men u emergente elems = new JRadioButtonMenuItem[ 3 ]; // elementos para seleccionar color // construir elemento men u, agregarlo al men u, habilitar manejo de eventos for ( int cont = 0; cont < elems.length; cont++ ) { elems[ cont ] = new JRadioButtonMenuItem( nombColores[ cont ] ); menuEmergente.add( elems[ cont ] ); // agregar elemento al men u emergente colorGroup.add( elems[ cont ] ); // agregar elemento al grupo bot on elems[ cont ].addActionListener( manejador ); // agregar manejador

110
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 } // fin del for

Componentes GUI

getContentPane().setBackground( Color.WHITE ); // poner fondo blanco // declarar un MouseListener para la ventana para mostrar men u emergente addMouseListener( new MouseAdapter() { // clase an onima interna // manejar evento rat on presionado public void mousePressed( MouseEvent event ) { revisarPorEventoDisparado( event ); // revisar por disparo } // fin del m etodo mousePressed // manejar evento rat on liberado public void mouseReleased( MouseEvent event ) { revisarPorEventoDisparado( event ); // revisar por disparo } // fin del m etodo mouseReleased // determinar si el evento deber a mostrar men u emergente private void revisarPorEventoDisparado( MouseEvent event ) { if ( event.isPopupTrigger() ) menuEmergente.show( event.getComponent(), event.getX(), event.getY() ); } // fin del m etodo revisarPorEventoDisparado } // fin de la clase an onima ); // fin de la llamada a addMouseListener } // fin del constructor VentanaPopup // clase interna privada para manejar los eventos de elementos men u private class ManejadorElemento implements ActionListener { // procesar las selecciones de elementos men u public void actionPerformed( ActionEvent event ) { // determinar cual elemento men u fue seleccionado for ( int i = 0; i < elems.length; i++ ) { if ( event.getSource() == elems[ i ] ) {

getContentPane().setBackground( colores[ i ] ); return;

3.21 JPopupMenu
84 } // fin del if 85 } // fin del for 86 } // fin del m etodo actionPerformed 87 } // fin de la clase privada interna ManejadorElemento 88 } // fin de la clase VentanaPopup

111

La l nea 25, en el constructor VentanaPopup de las l neas 2169, crea una instancia de la clase ManejadorElemento, que est a declarado en las l neas 7287, para procesar los eventos elemento de los elementos men u en el men u emergente. La l nea 29 crea el JPopupMenu. La sentencia for, l neas 33 39, crea un objeto JRadioButtonMenuItem, l nea 35, lo agrega al men u emergente en la l nea 36, lo agrega a grupoColor del tipo ButtonGroup en la l nea 37 para mantener un s olo JRadioButtonMenuItem seleccionada a la vez y registra su ActionListener en la l nea 38. La l nea 41 pone el fondo inicial a blanco invocando el m etodo setBackground. Las l neas 4468 registran un MouseListener para manejar los eventos rat on de la ventana de aplicaci on. Los m etodos mousePressed, l neas 4952, y mouseReleased, l neas 5558 revisan el evento disparador emergente. Cada m etodo llama al m etodo utilidad privado revisarPorEventoDisparado, l neas 6166, para determinar si ocurri o un evento disparador emergente. Si este sucedi o, el m etodo isPopupTrigger de MouseEvent regresa true, y el m etodo show de JPopupMenu muestra el JPopupMenu. El primer argumento al m etodo show indica el componente origen, cuya posici on ayuda a determinar donde el JPopupMenu aparecer a en la pantalla, los u ltimos dos argumentos son las coordenadas xy , medidas desde la esquina superior izquierda del componente origen, en el cual el JPopupMenu aparecer a. Cuando el usuario selecciona un elemento men u de men u emergente, el m etodo actionPerformed de la clase ManejadorElemento, l neas 7586, determina cual JRadioButtonMenuItem el usuario seleccion o y pone el color del fondo del panel de la ventana.
1 2 3 4 5 6 7 8 9 10 // PruebaPopup.java // Probando VentanaPopup. import javax.swing.JFrame; public class PruebaPopup {

public static void main( String args[] ) { VentanaPopup ventanaPopup = new VentanaPopup(); // crear VentanaPopup ventanaPopup.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

112

Componentes GUI

11 ventanaPopup.setSize( 300, 200 ); // fijar tama~ no de la ventana 12 ventanaPopup.setVisible( true ); // mostrar ventana 13 } // fin del main 14 } // fin de la clase PruebaPopup

3.22.

JTabbedPane

Un JTabbedPane arregla los componentes GUI en capas, de las cuales s olo una es visible a la vez. Los usuarios acceden cada capa mediante una pesta naparecida a las carpertas en un archivero. Cuando el usuario pulsa una pesta na, la capa apropiada es mostrada. Las pesta nas aparecen en la parte superior por defecto pero pueden ser posicionadas a la izquierda, derecha o abajo del JTabbedPane. Cualquier componente puede ser colocado en una pesta na. Si el componente es un contenedor, como un panel, este puede usar cualquier manejador de dise no para acomodar varios componentes en la pesta na. La clase JTabbedPane es una subclase de JComponent. La siguiente aplicaci on crea una ventana de pesta nas con tres de estas. Cada pesta na muestra uno de los JPanelpanel1, panel2, y panel3 y sus componentes GUI.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // VentanaJTabbedPane.java // Demostrando JTabbedPane. import java.awt.BorderLayout; import java.awt.Color; import javax.swing.JFrame; import javax.swing.JTabbedPane; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JButton; import javax.swing.SwingConstants; public class VentanaJTabbedPane extends JFrame // configurar GUI public VentanaJTabbedPane() { super( "Demo JTabbedPane" ); JTabbedPane panelPesta~ nas = new JTabbedPane(); // crear JTabbedPane // configurar pane11 y agregarlo al JTabbedPane {

3.22 JTabbedPane

113

22 JLabel etiq1 = new JLabel( "panel uno", SwingConstants.CENTER ); 23 JPanel panel1 = new JPanel(); // crear primer panel 24 panel1.add( etiq1 ); // agregar etiqueta a panel 25 panelPesta~ nas.addTab( "Pesta~ na Uno", null, panel1, "Primer Panel" ); 26 27 // configurar pane12 y agregarlo al JTabbedPane 28 JLabel label2 = new JLabel( "panel dos", SwingConstants.CENTER ); 29 JPanel panel2 = new JPanel(); // crear segundo panel 30 panel2.setBackground( Color.YELLOW ); // poner fondo amarillo 31 panel2.add( label2 ); // agregar etiqueta a panel 32 panelPesta~ nas.addTab( "Pesta~ na Dos", null, panel2, "Segundo Panel" ); 33 34 // configurar pane13 y agregarlo al JTabbedPane 35 JLabel label3 = new JLabel( "panel tres" ); 36 JPanel panel3 = new JPanel(); // crear tercer panel 37 panel3.setLayout( new BorderLayout() ); // usar borderlayout 38 panel3.add( new JButton( "Norte" ), BorderLayout.NORTH ); 39 panel3.add( new JButton( "Oeste" ), BorderLayout.WEST ); 40 panel3.add( new JButton( "Este" ), BorderLayout.EAST ); 41 panel3.add( new JButton( "Sur" ), BorderLayout.SOUTH ); 42 panel3.add( label3, BorderLayout.CENTER ); 43 panelPesta~ nas.addTab( "Pesta~ na Tres", null, panel3, "Tercer Panel" ); 44 45 add( panelPesta~ nas ); // agregar JTabbedPane a la ventana 46 } // fin del constructor VentanaJTabbedPane 47 } // fin de la clase VentanaJTabbedPane

El constructor, l neas 1546, construye la GUI. La l nea 19 crea un JTabbedPane vac o con la conguraci on por defectoesto es, las pesta nas en la parte superior. Si las pesta nas no caben en una l nea, estas son acomodadas para formar l neas adicionales de pesta nas. Despu es el constructor crea los paneles panel1, panel2 y panel3 y sus componentes GUI. Conforme se va congurando cada panel, se va agregando este al panel de pesta nas, usando el m etodo addTab de JTabbedPane con cuatro argumentos. El primer argumento es una cadena que indica el t tulo de la pesta na. El segundo argumento es una referencia tipo Icon que indica la imagen que se muestra en la pesta na. Si esta es una referencia null, no se muestra imagen. El tercer argumento es una referencia Component que representa el componente GUI que se muestra cuando el usuario pulsa la pesta na. El u ltimo argumento es una cadena que indica la sugerencia para la pesta na. Por ejemplo, la l nea 25 agrega panel1 del tipo JPanel a panelPesta~ nas con t tulo Pesta na Uno y la sugerencia Primer Panel. Los JPanel panel2 y panel3 son agregados a panelPesta~ nas en las

114

Componentes GUI

l neas 32 y 43. Para ver una pesta na, pulsar con el rat on o usar las teclas de navegaci on para ciclar a trav es de las pesta nas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // DemoJTabbedPane.java // Mostrando JTabbedPane. import javax.swing.JFrame; public class DemoJTabbedPane { public static void main( String args[] ) { VentanaJTabbedPane ventanaPesta~ nas = new VentanaJTabbedPane(); ventanaPesta~ nas.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); ventanaPesta~ nas.setSize( 250, 200 ); // fijar tama~ no de la ventana ventanaPesta~ nas.setVisible( true ); // mostrar ventana } // fin de main } // fin de la clase DemoJTabbedPane

3.23.

Manejador de Dise no: BoxLayout

El manejador de dise no BoxLayout permite que los componentes GUI sean arreglados de izquierda a derecha y de arriba hacia abajo en un contenedor. La clase Box declara un contenedor con BoxLayout como su manejador de dise no y proporciona m etodos est aticos para crear un Box con un BoxLayout horizontal o vertical. La aplicaci on siguiente muestra un BoxLayout y la clase contenedora Box que usa BoxLayout como su manejador de dise no por defecto.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // VentanaBoxLayout.java // Demostrando BoxLayout. import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.Box; import javax.swing.JButton; import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.JTabbedPane; public class VentanaBoxLayout extends JFrame // configurar GUI public VentanaBoxLayout() { {

3.23 Manejador de Dise no: BoxLayout


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 58 59

115

super( "Mostrando BoxLayout" ); // crear contenedores Box que tienen BoxLayout Box horizontal1 = Box.createHorizontalBox(); Box vertical1 = Box.createVerticalBox(); Box horizontal2 = Box.createHorizontalBox(); Box vertical2 = Box.createVerticalBox(); final int TAM = 3; // n umero de botones en cada BOX // agregar botones a horizontal1 for ( int cont = 0; cont < TAM; cont++ ) horizontal1.add( new JButton( "Bot on " + cont ) ); // crear puntal y agregar botones a vertical1 for ( int cont = 0; cont < TAM; cont++ ) { vertical1.add( Box.createVerticalStrut( 25 ) ); vertical1.add( new JButton( "Bot on " + cont ) ); } // fin del for // crear pegamento horizontal y agregar botones a horizontal2 for ( int cont = 0; cont < TAM; cont++ ) { horizontal2.add( Box.createHorizontalGlue() ); horizontal2.add( new JButton( "Bot on " + cont ) ); } // fin del for // crear area r gida y agregar botones a vertical2 for ( int cont = 0; cont < TAM; cont++ ) { vertical2.add( Box.createRigidArea( new Dimension( 12, 8 ) ) ); vertical2.add( new JButton( "Bot on " + cont ) ); } // fin del for // crear pegamento vertical y agregar botones al panel. JPanel panel = new JPanel(); panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ) ); for ( int cont = 0; cont < TAM; cont++ ) {

panel.add( Box.createGlue() ); panel.add( new JButton( "Bot on " + cont ) ); } // fin del for

116

Componentes GUI

60 61 // crear a JTabbedPane 62 JTabbedPane tabs = new JTabbedPane( 63 JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT ); 64 65 // colocar cada contenedor en en un panel de pesta~ nas. 66 tabs.addTab( "Caja Horizontal", horizontal1 ); 67 tabs.addTab( "Caja Vertical con Puntales", vertical1 ); 68 tabs.addTab( "Caja Horizontal con Pegamento", horizontal2 ); 69 tabs.addTab( "Caja Vertical con Areas R gidas", vertical2 ); 70 tabs.addTab( "Caja Vertical con Pegamento", panel ); 71 72 add( tabs ); // colocar panel de pesta~ nas en la ventana 73 } // fin del constructor de la clase VentanaBoxLayout 74 } // fin de clase VentanaBoxLayout

Las l neas 1922 crea contenedores Box. Las referencias horizontal1 y horizontal2 son inicializadas con el m etodo est atico createHorizontalBox de Box, la cual regresa un contenedor Box con un BoxLayout horizontal en el cual los componentes GUI son arreglados de izquierda a derecha. Las variables vertical1 y vertical2 son inicializadas con el m etodo est atico createVerticalBox, el cual regresa referencias a contenedores Box con un BoxLayout vertical en el cual los componentes GUI son arreglados de arriba hacia abajo. La sentencia for en las l neas 2728 agregan tres JButton a horizontal1. La sentencia for en las l neas 3135 agregan tres JButton a vertical1. Antes de agregar cada bot on, la l nea 33 agregra un puntal vertical al contenedor con el m etodo est atico createVerticalStrut de Box. Un puntal vertical es un componente GUI invisible que tiene una altura ja de p xeles y est a es usada para garantizar una cantidad ja de espacio entre los componentes GUI. El argumento entero al m etodo createVerticalStrut determina la altura del puntal en p xeles. Cuando el contenedor es redimensionado, la distancia entre los componentes GUI separados por puntales no cambian. La clase Box tambi en declara el m etodo createHorizontalStrut para BoxLayout horizontales. La sentencia for en las l neas 3842 agrega tres JButton a horizontal2. Antes de agregar cada bot on, la l nea 40 agrega pegamento horizontal al contenedor con el m etodo est atico createHorizontalGlue de Box. El pegamento horizontal es un componente invisible que puede ser usado entre componentes GUI de tama no jo para ocupar espacio adicional. Normalmente,

3.23 Manejador de Dise no: BoxLayout

117

espacio extra aparece a la derecha del u ltimo componente GUI horizontal o abaja de la u ltimo vertical en un BoxLayout. El pegamento permite que el espacio extra sea colocado entre los componentes GUI. Cuando el contenedor es redimensionado, los componentes separados por componentes cemento permanecen del mismo tama no, pero el cemento se estrecha o contrae para ocupar el espacio entre ellos. La clase Box tambi en declara el m etodo createVerticalGlue para BoxLayout verticales. La sentencia en las l neas 4549 agrega tres JButton a vertical2. Antes de que cada bot on sea agregado, la l nea 47 agrega una area rigida al contenedo con el m etodo est atico createRigidArea. Una area r gida es un componente invisible GUI que siempre tiene jo un ancho y alto. El argumento al m etodo createRigidArea es un objeto Dimension que indica la altura y el ancho del area. Las l neas 5253 crean un objeto JPanel y ja su manejador a un BoxLayout en la forma convencional, usando el m etodo setLayout de Container. El constructor BoxLayout recibe una referencia al contenedor para el cual controla el manejador y una constante indicando si el manejador es horizontal con BoxLayout.X AXIS, o vertical empleando BoxLayout.Y AXIS. La sentencia for en las l neas 5559 agregan tres JButton al panel. Antes de agregar cada bot on, la l nea 57 agrega un componente pegamento al contenedor con el m etodo est atico createGlue. Este componente se expande o contrae basado en el tama no de la caja. Las l neas 6263 crea un JTabbedPane para mostrar los cinco contenedores en este programa. El argumento JTabbedPane.TOP indica en el constructor que las pesta nas deber an aparecer en la parte superior. El argumento an desplaJTabbedPane.SCROLL TAB LAYOUT indica que las etiquetas deber zarse si hay muchas para caber en una l nea. Los contenedores Box y el JPanel son agregados al JTabbedPane en las l neas 6670.
1 2 3 4 5 6 7 8 9 10 // DemoBoxLayout.java // Demostrando BoxLayout. import javax.swing.JFrame; public class DemoBoxLayout { public static void main( String args[] ) { VentanaBoxLayout boxLayoutFrame = new VentanaBoxLayout(); boxLayoutFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

118

Componentes GUI

11 boxLayoutFrame.setSize( 400, 220 ); // fijar tama~ no ventana 12 boxLayoutFrame.setVisible( true ); // mostrar ventana 13 } // fin de main 14 } // fin de la clase DemoBoxLayout

Bibliograf a
[1] H. M. Deitel, Java How to Program, Sevent Edition, Prentice Hall, 2007. [2] J. Friesen, Java SE 6 Platform: From Novice to Professional, Apress, 2007.

También podría gustarte