119
Interfaces Gr´ aficas de Usuario con JAVA ector Tejeda V Febrero, 2010

notasGUI

Embed Size (px)

Citation preview

  • Interfaces Graficas de Usuario con JAVA

    Hector Tejeda V

    Febrero, 2010

  • 2

  • Indice general

    1. Introduccion 51.1. Componentes, disenadores y eventos . . . . . . . . . . . . . . 61.2. AWT y Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

    2. Caso de estudio 92.1. Mostrando texto en un cuadro de dialogo . . . . . . . . . . . . 92.2. Ingresando texto en un cuadro de dialogo . . . . . . . . . . . . 10

    2.2.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 112.3. Creando dibujos simples . . . . . . . . . . . . . . . . . . . . . 12

    2.3.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 152.4. Dibujando rectangulos y elipses . . . . . . . . . . . . . . . . . 16

    2.4.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 182.5. Figuras Rellenas y Colores . . . . . . . . . . . . . . . . . . . . 19

    2.5.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 212.6. Dibujo de Arcos . . . . . . . . . . . . . . . . . . . . . . . . . . 22

    2.6.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 242.7. Usando objetos con graficas . . . . . . . . . . . . . . . . . . . 25

    2.7.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 282.8. Texto e imagenes con etiquetas . . . . . . . . . . . . . . . . . 30

    2.8.1. Ejercicio . . . . . . . . . . . . . . . . . . . . . . . . . . 322.9. Dibujado con polimorfismo . . . . . . . . . . . . . . . . . . . . 32

    2.9.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 32

    3. Componentes GUI 353.1. Introduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.2. Generalidades de Componentes Swing . . . . . . . . . . . . . . 353.3. Mostrar texto e imagenes en una ventana . . . . . . . . . . . . 383.4. Campos de texto y eventos . . . . . . . . . . . . . . . . . . . . 42

  • 4 INDICE GENERAL

    3.5. Tipos de eventos e interfaces receptoras . . . . . . . . . . . . . 493.6. Como trabaja el manejador de eventos . . . . . . . . . . . . . 513.7. JButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533.8. Botones que mantienen estado . . . . . . . . . . . . . . . . . . 56

    3.8.1. JCheckBox . . . . . . . . . . . . . . . . . . . . . . . . 573.8.2. JRadioButton . . . . . . . . . . . . . . . . . . . . . . . 60

    3.9. JComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643.10. JList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663.11. Listas de seleccion multiple . . . . . . . . . . . . . . . . . . . 683.12. Manejo de eventos del raton . . . . . . . . . . . . . . . . . . . 713.13. Clases adaptadoras . . . . . . . . . . . . . . . . . . . . . . . . 753.14. Subclase JPanel para dibujar con el raton . . . . . . . . . . . 783.15. Manejo de eventos del teclado . . . . . . . . . . . . . . . . . . 823.16. Manejadores de diseno . . . . . . . . . . . . . . . . . . . . . . 85

    3.16.1. FlowLayout . . . . . . . . . . . . . . . . . . . . . . . . 873.16.2. BorderLayout . . . . . . . . . . . . . . . . . . . . . . . 903.16.3. GridLayout . . . . . . . . . . . . . . . . . . . . . . . . 93

    3.17. Paneles anidados . . . . . . . . . . . . . . . . . . . . . . . . . 953.18. JTextArea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 973.19. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993.20. Usando Menus con Frames . . . . . . . . . . . . . . . . . . . . 1003.21. JPopupMenu . . . . . . . . . . . . . . . . . . . . . . . . . . . 1083.22. JTabbedPane . . . . . . . . . . . . . . . . . . . . . . . . . . . 1123.23. Manejador de Diseno: BoxLayout . . . . . . . . . . . . . . . . 114

  • Captulo 1

    Introduccion

    Se presenta en este material, ejemplos que no son considerados en uncurso introductorio de Java, ya que las aplicaciones que se revisan tieneninterfaces de usuario que utilizan exclusivamente texto. La razon por la cualson usadas estas interfaces textuales no es, porque tengan una gran ventaja;en realidad, la unica ventaja que tienen es su facilidad para ser creadas.

    Por lo general, en un curso introductorio de Java se pretende no distraermucho la atencion del estudiante en las cuestiones importantes del desarrollode software; por lo que en general la mayora de los cursos introductorios secentran en cuestiones relacionadas con la estructura y la interaccion de losobjetos, el diseno de clases y la calidad del codigo.

    Las interfaces graficas de usuario o GUI (Graphical User Interface) sontambien construidas usando objetos que interactuan, pero cuentan con unaestructura muy especializada y es por lo anterior que se evita usarlas antes deaprender la estructura de los objetos en terminos mas generales. Una vez quese tienen las bases, se esta preparado para dar una mirada a la construccionde las GUI.

    Las GUI completan las aplicaciones con una interfaz formada por venta-nas, menus, botones y otros componentes graficos, y hacen que la aplicaciontenga una apariencia mas parecida a las aplicaciones tpicas, que son usadaspor la mayora de la gente que usa un sistema de computo.

    Se debe observar el doble significado de la palabra interfaz. Las interfacesde las que se abordan en este material no son las interfaces de las clasesni la construccion interfaz de Java. Cuando se dice interfaces de usuario,se refiere a la parte de una aplicacion que esta visible en la pantalla y quepermite que un usuario interactue con ella.

  • 6 Introduccion

    Una vez que se sabe como crear una GUI en Java, se pueden desarrollarprogramas que tengan una mejor presentacion visual.

    1.1. Componentes, gestores de disposicion y

    captura de eventos

    Para la creacion de una GUI son varios los detalles que estan involucrados.En este material no se cubren todos los detalles de las distintas tareas quese pueden hacer, solo se discuten los principios generales y un buen numerode ejemplos.

    En Java, toda la programacion de una GUI se hace mediante el uso debibliotecas de clases estandares especializadas. Una vez que se han compren-dido los principios se pueden encontrar todos los detalles necesarios en ladocumentacion de la biblioteca estandar.

    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 enla pantalla.

    3. La forma como se debe responder a una entrada del usuario.

    Se discuten los puntos anteriores mediante los terminos componentes,gestores de dispositivos y manejo de eventos respectivamente.

    Los componentes son las partes individuales con las cuales se construyeuna GUI. Ejemplos de estos son los botones, los menus, los elementos delmenu, las cajas de verificacion, los deslizadores, los campos de texto, etc. Labiblioteca de Java contiene una cantidad de componentes disenados para serusados inmediatamente y tambien es posible que el programador escriba suspropios componentes. Es necesario que se aprenda cuales son los componen-tes importantes, como son creados y como hacer para que aparezcan en lapantalla tal cual se desea verlos.

    Los gestores de disposicion son empleados en la ubicacion de los compo-nentes en la pantalla. Los sistemas de GUI mas viejos y primitivos manejabancoordenadas bidimensionales, donde el programador indicaba mediante unpar ordenado de valores, que expresaban un valor en pxeles, la posicion delcomponente ademas del alto y el ancho del mismo. En los sistemas de GUI

  • 1.2 AWT y Swing 7

    mas modernos, esta forma es muy simple, ya que se debe tener en cuenta lasdistintas resoluciones de pantalla, las diferentes fuentes, las ventanas que losusuarios pueden redimensionar, y otros aspectos que hacen difcil la distribu-cion de los componentes. La solucion es un esquema donde el programadorpueda indicar la disposicion de los componentes en terminos mas generales.Por ejemplo, se puede indicar que este componente debera estar debajo deeste otro o que este componente se estrechara cuando la ventana cambiede tamano pero este otro tendra un tamano constante. Lo anterior se lograusando los gestores de disposicion.

    El manejo de eventos se refiere a la tecnica que se usa para respondera las entradas del usuario. Una vez que los componentes han sido creado yque han sido posicionados en la pantalla, es necesario asegurar de que ocurraalgo cuando el usuario presione un boton, por ejemplo. El modelo que usa labiblioteca de Java para lograr lo anterior esta basada en eventos: si un usuarioactiva un componente, por ejemplo, por pulsar un boton o seleccionar unelemento de un menu, el sistema generara un evento. Entonces, la aplicacionpuede recibir una notificacion del evento, mediante la invocacion de uno desus metodos, y se puede llevar a cabo la accion adecuada.

    1.2. AWT y Swing

    Java tiene dos bibliotecas para la construccion de interfaces graficas deusuario. La mas antigua, denominada AWT (Abstract Window Toolkit), fueintroducida con el primer sistema Java original; mas tarde, se agrego unamejor biblioteca denominada Swing.

    Swing utiliza algunas de las clases de la biblioteca AWT, reemplaza algu-nas de las clases de AWT con sus propias versiones y agrega clases nuevas.

    En este material, se usara la biblioteca Swing, aunque se usaran algunasde las clases de AWT que todava son empleadas en los programas Swing.Para el caso de que existan clases equivalentes en ambas bibliotecas, se usaranlas versiones de Swing.

    Como existen clases equivalentes en AWT y en Swing, las versiones Swinghan sido identificadas mediante el agregado de la letra ((J)) al comienzo delnombre de la clase. Por ejemplo, existen las clases de nombre Button yJButton, Frame y JFrame, Menu y JMenu, etc. Las clases que comienzan con((J)) son versiones Swing; y seran las unicas que se usaran.

  • 8 Introduccion

  • Captulo 2

    Caso de estudio

    Este caso de estudio esta disenado para iniciar el aprendizaje de las poten-tes capacidades de Java para crear GUIs. Se muestran diez secciones breves,en donde cada seccion introduce unos cuantos conceptos basicos y propor-ciona ejemplos visuales graficos. En las secciones subsecuentes, se empleanconceptos de la programacion orientada a objetos para crear aplicaciones quedibujan una variedad de figuras.

    2.1. Mostrando texto en un cuadro de dialo-

    go

    Muchas aplicaciones usan ventanas o cuadros de dialogo, tambien lla-mados dialogos para mostrar la salida. Por ejemplo, los navegadores comoFirefox o Microsoft Internet Explorer muestran paginas web en su propiaventana. Programas de correo electronico permiten teclear y leer mensajesen una ventana. Tpicamente, los cuadros de dialogo son ventanas en lascuales los programas muestran mensajes importantes a los usuarios. La cla-se JOptionPane proporciona cuadros de dialogo empaquetados previamenteque permiten a los programas mostrar ventanas conteniendo ventanas tales ventanas son llamadas dialogos de mensaje. El codigo que se muestra acontinuacion muestra la cadena Bienvenido a Java en tres renglones.

    1 // Dialogo1.java

    2 // Imprimiendo multiples lneas en un cuadro de dialogo

    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 dialogo con un mensaje

    8 JOptionPane.showMessageDialog( null, "Bienvenido\na\nJava" );

    9 } // fin del main

    10 } // fin del cuadro de dialogo

    En la lnea 3 se indica que el programa usara la clase JOptionPane del pa-quete javax.swing. Este paquete contiene varias clases que ayudan a crear laGUI para las aplicaciones. Los componentes GUI facilitan la entrada de datospara un usuario, y la presentacion de datos al usuario. La lnea 8 llama almetodo showMessageDialog para mostrar un cuadro de dialogo conteniendoun mensaje. El metodo requiere dos argumentos. El primer argumento de-termina el Frame al cual es asociado el dialogo, si es null se asocia con elFrame por defecto. El segundo argumento es el String que sera mostradoen el dialogo.

    El metodo showMessageDialog es un metodo estatico de la clase JOptionPane.Los metodos estaticos definen frecuentemente tareas usadas que no requierenla creacion explcita de un objeto. Por ejemplo, muchos programas muestrancuadros de dialogo, y en vez de requerir que se cree codigo que haga la ta-rea, los disenadores de la clase JOptionPane declararon un metodo estaticoque realiza la tarea del programador. Un metodo estatico generalmente esllamado usando el nombre de la clase seguido por un punto y el nombre delmetodo.

    2.2. Ingresando texto en un cuadro de dialo-

    go

    La aplicacion que se muestra enseguida usa otro cuadro de dialogo pre-definido JOptionPane llamado dialogo de entrada, que permite al usuarioingresar datos en el programa. El programa pide el nombre del usuario, yresponde con un cuadro de mensaje conteniendo un saludo y el nombre queel usuario haya ingresado.

    1 // NombreDialogo.java

    2 // Entrada Basica con un cuadro de dialogo.

    3

    4 import javax.swing.JOptionPane;

    5 public class NombreDialogo {

  • 2.2 Ingresando texto en un cuadro de dialogo 11

    6

    7 public static void main( String args[] ) {

    8 // solicitar al usuario que ingrese un nombre

    9 String nombre =

    10 JOptionPane.showInputDialog( "Cual es tu nombre?" );

    11 // crear el mensaje

    12 String mensaje = String.format(

    13 "Bienvenido, %s, a la Programacion 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 lneas 910 usan el metodo showInputDialog de JOptionPane paramostrar un dialogo de entrada conteniendo un mensaje y un campo, conocidocomo campo de texto, en el cual el usuario puede poner texto. El argumentopasado al metodo es el mensaje que indica lo que el usuario debera ingresar.El usuario teclea caracteres en el campo de texto, y despues pulsa el botonAceptar o tambien puede presionar la tecla Intro para mandar la cadena alprograma. El metodo showInputDialog devuelve un String conteniendo loscaracteres tecleados por el usuario. La cadena es almacenada en la variablenombre. Si se presiona el boton Cancelar en el dialogo, el metodo regresanull y el programa muestra la palabra null como el nombre.

    Las lneas 1213 usan el metodo estatico format que devuelve un Stringpara regresar una cadena conteniendo el saludo con el nombre del usuario.El metodo format es parecido al metodo System.out.printf, excepto queformat regresa la cadena formateada en vez de mostrarla. La lnea 14 muestrael saludo en un mensaje de dialogo.

    2.2.1. Ejercicios

    1. Escribir un programa que use entradas y salidas con cuadros de dialogocon los metodos de la clase JOptionPane para multiplicar dos numeros.Como el metodo showInputDialog regrese un String, se debera con-vertir el String ingresado por el usuario a un tipo int para hacer elcalculo. El metodo

    Integer.parseInt( String s )

    toma un argumento tipo String representando un entero y regresa elvalor como un tipo int. El metodo parseInt es un metodo estatico de

  • 12 Caso de estudio

    la clase Integer del paquete java.lang.

    2.3. Creando dibujos simples

    Una de las caractersticas de Java es el soporte de graficos que permitea los programadores visualmente resaltar sus aplicaciones. En esta seccionse muestra una de las capacidades graficas de Java dibujado de lneas.Tambien se cubre lo basico para la creacion de una ventana para mostrar undibujo sobre la pantalla de la computadora.

    Para dibujar en Java, se requiere entender el sistema de coordenadas, unesquema para identificar cada punto en la pantalla. Por defecto, la esquinasuperior izquierda de un componente GUI tiene coordenadas (0,0). Una parcoordenado esta compuesto de un coordenada en x, en este caso la coordenadahorizontal, y una coordena en y, la coordenada vertical. La coordenada en xes la localidad horizontal moviendose de izquierda a derecha. La coordenadaen y es la localidad vertical moviendose de arriba hacia abajo.

    Las coordenadas indican donde el grafico debera ser mostrado en pantalla.Las unidades de las coordenadas estan medidas en pxeles. Un pixel es launidad mas pequena de resolucion que despliega el monitor. El termino pixelviene de las palabras del ingles picture element.

    La aplicacion que se muestra a continuacion solo dibuja dos lneas. La cla-se DibujaPanel realiza el dibujo actual, mientras la clase DibujaPanelPruebacrea una ventana para mostrar el dibujo. En la clase DibujaPanel, las sen-tencias import en las lneas 45 permiten usar la clase Graphics del paquetejava.awt, el cual proporciona varios metodos para dibujar texto y figurassobre la pantalla, y la clase JPanel del paquete javax.swing proporcionauna area sobre la cual se puede dibujar.

    1 // Clase DibujaPanel.java

    2 // Usando drawLine para conectar las esquinas de un panel.

    3

    4 import java.awt.Graphics;

    5 import javax.swing.JPanel;

    6

    7 public class DibujaPanel extends JPanel {

    8

    9 // dibujar una X desde las esquinas del panel

    10 public void paintComponent( Graphics g ) {

    11

  • 2.3 Creando dibujos simples 13

    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 lnea desde la izquierda superior

    19 // hasta la derecha inferior

    20 g.drawLine( 0, 0, ancho, alto );

    21

    22 // dibujar una lnea desde la izquierda inferior

    23 // hasta la derecha superior

    24 g.drawLine( 0, alto, ancho, 0 );

    25 } // fin del metodo paintComponent

    26 } // fin de la clase DibujaPanel

    En la lnea 7 se usa la palabra reservada extends para indicar que laclase DibujaPanel es una mejora del tipo JPanel. Con extends se indicauna relacion de herencia en la cual la clase DibujaPanel inicia con los miem-bros existentes (datos y metodos) de la clase JPanel. La clase desde la cualDibujaPanel hereda, JPanel, aparece a la derecha de la palabra extends.En esta relacion de herencia, JPanel es llamada la superclase y DibujaPaneles llamada la subclase. Con lo anterior se obtiene que la clase DibujaPaneltenga los atributos (datos) y comportamiento (metodos) de la clase JPanely ademas las nuevas caractersticas que se agregan en la declaracion de laclase DibujaPanel especficamente, la habilidad para dibujar dos lneas alo largo de las diagonales del panel.

    Cada JPanel, incluyendo DibujaPanel, tienen un metodo paintComponent,lneas 1025, el cual es llamado por el sistema automaticamente cada vezque se necesita mostrar el JPanel. Este metodo debera ser sobreescrito si sedesea dibujar algo en el panel. Este metodo es llamado cuando un JPanel esmostrado por primera vez en la pantalla, cuando este es cubierto y despuesdescubierto por alguna ventana, y cuando la ventana es redimensionada. Estemetodo requiere un argumento, un objeto Graphics, que es proporcionadopor el sistema cuando se llama a paintComponent.

    La primera sentencia en cada metodo paintComponent que sobreescribaal metodo heredado debera ser

    super.paintComponent( g );

    lo cual asegura que el panel es dibujado apropiadamente en la pantalla antesde iniciar el dibujo. En las lneas 15 y 16 se llaman dos metodos que la

  • 14 Caso de estudio

    clase DibujaPanel hereda de la clase JPanel, en general, cualquier claseque extienda a otra, podra usar cualquier metodo que este declarado enla superclase que tenga al modificador public. Los metodos getWidth ygetHeight regresan el ancho y el alto del JPanel respectivamente, los cualesson almacenados en las variables que estan declaradas en las lneas 15 y 16.En las lneas 20 y 24 se usa la referencia g del tipo Graphics para llamar almetodo drawLine que dibujara las lneas. Los primeros dos argumentos, delmetodo drawLine, son las coordenadas de un extremo de la lnea, y los otrosdos son las coordenadas del otro extremo. Si se redimensiona la ventana laslneas seran escaladas automaticamente, ya que los argumentos estan basadosen el ancho y alto del panel. Redimensionando la ventana en esta aplicacionprovoca que el sistema llame al metodo paintComponent para redibujar elcontenido de DibujaPanel.

    Para mostrar DibujaPanel en la pantalla, se debera colocar este dentro deuna ventana. Se puede crear una ventana con un objeto de la clase JFrame. EnDibujaPanelPrueba, que se muestra enseguida, la lnea 4 se importa la claseJFrame del paquete javax.swing. En la lnea 11 en el metodo main de la cla-se DibujaPanelPrueba se crea una instancia de la clase DibujaPanel, la cualcontendra el dibujo, y la lnea 14 crea un nuevo JFrame que puede contener ymostrar el panel. La lnea 17 llama al metodo setDefaultCloseOperationcon el argumento JFrame.EXIT ON CLOSE para indicar que la aplicacion de-bera terminar cuando el usuario cierre la ventana. La lnea 17 usa el metodoadd de la clase JFrame para poner el panel conteniendo el dibujo en el frame.La lnea 19 pone el tamano del frame, empleando el metodo size dandoledos parametros el ancho del frame, y el alto. En la lnea 20 se muestra elJFrame.

    1 // DibujaPanelPrueba.java

    2 // Aplicacion para montar un DibujaPanel.

    3

    4 import javax.swing.JFrame;

    5

    6 public class DibujaPanelPrueba {

    7

    8 public static void main( String args[] ) {

    9

    10 // crear un panel que contenga el dibujo

    11 DibujaPanel panel = new DibujaPanel();

    12

    13 // crear un nuevo frame para contener al panel

  • 2.3 Creando dibujos simples 15

    14 JFrame aplicacion = new JFrame();

    15

    16 // indicar que al salir del frame se cierre la aplicacion

    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

    2.3.1. Ejercicios

    1. Usando ciclos y sentencias de control dibujar lneas para obtener disenosinteresantes.

    a) Crear un diseno que dibuje lneas desde la esquina superior izquier-da, desplegandose en abanico hasta que cubran la mitad superiorizquierda del panel. Una aproximacion es dividir el ancho y altoen un numero igual de pedazos (15 pedazos estara bien). El pri-mer extremo de una lnea siempre estara en la esquina superiorizquierda (0,0), El segundo extremo puede encontrarse iniciandoen la esquina inferior izquierda, luego moverse hacia arriba un pe-dazo vertical y un pedazo horizontal a la derecha. Dibujar unalnea entre los dos extremos. Continuarse moviendo el extremo,arriba y a la derecha, hasta llegar a la esquina superior derecha.La figura se debera ajustar cuando se redimensione la ventana.

    b) Modificiar el programa del ejercicio anterior para desplegar lneasdesde las cuatro esquinas. Las lneas de las esquinas opuestas sedeberan intersectar.

    2. Realizar los siguientes programas.

    a) Crear un diseno iniciando con la division de cada lado del panelen la misma cantidad de partes, se puede escoger 15. La primeralnea inicia en la esquina superior izquierda y termina una partea la derecha sobre el lado inferior. Para las siguientes lneas, sedebera mover hacia abajo en una parte del lado izquierdo, y unaparte hacia la derecha en el lado inferior. Repetir lo anterior hastaque se alcance en el lado inferior la esquina inferior derecha.

  • 16 Caso de estudio

    b) Modificar el programa del ejercicio anterior para espejear el disenoen las cuatro esquinas.

    2.4. Dibujando rectangulos y elipses

    En esta seccion se muestra como dibujar rectangulos y elipses, usando dela clase Graphics los metodos drawRect y drawOval respectivamente.

    1 // Figuras.java

    2 // Se muestran diferentes figuras que pueden ser dibujadas

    3 import java.awt.Graphics;

    4 import javax.swing.JPanel;

    5

    6 public class Figuras extends JPanel {

    7 private int opcion; // opcion del usuario de la figura a dibujar

    8

    9 // El constructor pone la opcion del usuario

    10 public Figuras( int opcionUsuario ) {

    11 opcion = opcionUsuario;

    12 } // fin del constructor Figuras

    13

    14 // dibujar una cascada de figuras iniciando desde la esquina

    15 // superior izquierda

    16 public void paintComponent( Graphics g ) {

    17 super.paintComponent( g );

    18 for ( int i = 0; i < 10; i++ ) {

    19 // selecionar la figura basandose en la opcion del usuario

    20 switch ( opcion ) {

    21 case 1: // dibujar rectangulos pasando las coordenadas del

    22 // rectangulo dado por la esquina x, y, con ancho y alt o

    23 g.drawRect( 10 + i * 10, 10 + i * 10,

    24 50 + i * 10, 50 + i * 10 );

    25 break;

    26 case 2: // dibujar elipses

    27 g.drawOval( 10 + i * 10, 10 + i * 10,

    28 50 + i * 10, 50 + i * 10 );

    29 break;

    30 } // fin del switch

    31 } // fin del for

    32 } // fin del metodo paintComponent

    33 } // fin de la clase Figuras

    La lnea 6 inicia con la declaracion de la clase Figuras, la cual extiendea la clase JPanel. La variable de instancia, opcion, declarada en la lnea 7,

  • 2.4 Dibujando rectangulos y elipses 17

    determina si el metodo paintComponent debera dibujar rectangulos o elipses.El constructor en las lneas 1012 inicializa opcion con el valor pasado en elparametro opcionUsuario.

    El metodo paintComponent, de las lneas 1632, hace el dibujo. No sedebe olvidar que la primera sentencia que debera ser llamada en este metodoes super.paintComponent, como aparece en la lnea 19. Entre las lneas 1831 se tiene un ciclo que dibuja 10 figuras. La sentencia switch, lneas 2030,selecciona entre dibujar rectangulos y elipses.

    Si opcion tiene 1, entonces el programa dibuja un rectangulo, mediantela llamada al metodo drawRect de la clase Graphics en las lneas 2324.Este metodo requiere cuatro argumentos, siendo los dos primeros las coor-denadas de la esquina superior izquierda del rectangulo, y los siguientes dosparametros representan el ancho y el alto del rectangulo. En este ejemplo seinicia en una posicion 10 pxeles abajo y 10 pxeles a la derecha de la esquinasuperior izquierda, y en cada iteracion del ciclo se mueve la esquina superiorizquierda otros 10 pxeles hacia abajo y a la derecha. El ancho y la alturadel rectangulo inician en 50 pxeles y se incrementan en 10 pxeles en cadaiteracion.

    Si opcion tiene 2, el programa dibuja una elipse. Cuando se dibuja unaelipse, se encuentra contenida en un rectangulo, bounding rectangle, y la elipsetoca los cuatro puntos medios del rectangulo. El metodo drawOval, lneas2728, requiere los mismos cuatro argumentos que el metodo drawRect. Losargumentos especifican la posicion y el tamano del rectangulo que acota ala elipse. Para este caso son los mismos valores que fueron dados para elrectangulo.

    Se muestra enseguida el programa que es el responsable para manejar laentrada del usuario y crear una ventana para desplegar los dibujos apropiadosusando la seleccion del usuario.

    1 // ProbarFiguras.java

    2 // Aplicacion de prueba que muestra la clase Figuras

    3

    4 import javax.swing.JFrame;

    5 import javax.swing.JOptionPane;

    6

    7 public class ProbarFiguras {

    8

    9 public static void main( String args[] ) {

    10 // obtener la opcion del usuario

    11 String entrada = JOptionPane.showInputDialog(

  • 18 Caso de estudio

    12 "Ingresar 1 para dibujar rectangulos\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 lneas 1113 se pide al usuario, con un cuadro de dialogo de entrada,que seleccione el tipo de figuras a dibujar; la respuesta es almacenada en lavariable entrada. En la lnea 15 se emplea el metodo parseInt de la claseInteger para convertir el String guardado en la variable entrada a un tipoint y se asigna a la variable opcion. Una instancia de la clase Figuras escreada en la lnea 17, pasando la opcion del usuario al constructor. Las lneas1722 realizan las operaciones habituales para crear y configurar la ventanacrear un frame, configurar salir cuando la aplicacion sea cerrada, agregarel dibujo al frame, configurar el tamano del frame y hacerlo visible.

    2.4.1. Ejercicios

    1. Dibujar 12 crculos concentricos en el centro de un JPanel. El crculomas interno debera tener un radio de 10 pxeles, y cada crculo sucesivodebera tener un radio de 10 pxeles mas grande que el previo anterior.Iniciar encontrando el centro del JPanel. Para obtener la esquina su-perior izquierda de un crculo moverse un radio hacia arriba y un radiohacia la izquierda desde el centro. El ancho y el alto del rectanguloacotador es el diametro del crculo (dos veces el radio).

    2. Crear un programa que lea la entrada de varios valores, usando cua-dros de dialogo, para mostrar una grafica de barras con rectangulos, deacuerdo a los valores dados.

  • 2.5 Figuras Rellenas y Colores 19

    2.5. Figuras Rellenas y Colores

    Se pueden crear muchos disenos interesantes con solo lneas y figuras basi-cas, la clase Graphics proporciona muchas mas capacidades. Se revisaran acontinuacion las caractersticas de colores y figuras rellenas. Agregando colorse agrega otra caracterstica a los dibujos que el usuario ve en la computado-ra. Las figuras rellenas cubren totalmente regiones con colores solidos, en vezde solo dibujar los contornos.

    Los colores mostrados en las pantallas de las computadoras estan defini-dos por sus partes de rojo, verde y azul. Estas partes, conocidos como valoresRGB (Red Green Blue), tiene valores enteros entre 0 y 255. Entre mas gran-de sea el valor, mayor tinte tendra el color final. Java emplea la clase Colordel paquete java.awt para representar colores usando sus valores RGB. Laclase Color en el paquete java.awt es empleada por Java para representarcolores usando los valores RGB. La clase Color contiene 13 objetos predefini-dos estaticos Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK GRAY,Color.GRAY, Color.GREEN, Color.LIGHT GRAY, Color.MAGENTA, Color.ORAN-GE, Color.PINK, Color.RED, Color.WHITE y Color.YELLOW. La clase Colortambien contiene un constructor de la forma:

    public Color( int r, int g, int b)

    para que se puedan crear colores hechos a la medida especificando los com-ponentes individuales rojo, verde y azul de un color.

    Los rectangulos y las elipses rellenas son dibujados con los metodos fillRecty fillOval de la clase Graphics, respectivamente. Estos dos metodos tie-nen los mismos parametros como sus contrapartes sin rillenar drawRect ydrawOval; los primeros dos parametros son las coordenadas para la esquinasuperior izquierda de la figura, mientras los siguientes dos parametros deter-minan su ancho y alto. El codigo de enseguida crea una cara sonriente, verfigura 2.1, empleando colores y figuras rellenas.

    1 // CaraSonriente.java

    2 // Muestra figuras rellenas

    3

    4 import java.awt.Color;

    5 import java.awt.Graphics;

    6 import javax.swing.JPanel;

    7

    8 class CaraSonriente extends JPanel {

  • 20 Caso de estudio

    Figura 2.1: Una cara sonriente empleando fillOval y la clasejava.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 metodo paintComponent

    26 } // fin de CaraSonriente

    Las sentencias import en las lneas 46 del codigo anterior importan lasclases Color, Graphics y JPanel. La clase CaraSonriente, lneas 1025, usala clase Color para especificar los colores de dibujo, y usa la clase Graphicspara dibujar. La clase JPanel proporciona el area en la cual se dibujara. Enla lnea 13 se emplea setColor de la clase Graphics para indicar el colorcon el que se dibujara usando el color amarillo. El metodo setColor requiereun argumento, el color que sera puesto como el color para dibujar. La lnea14 dibuja un crculo con diametro 200 para representar la cara. En la lnea16 se pone el color negro, y las lneas 17 y 18 ponen los ojos. La boca sedibuja con una elipse en la lnea 20, pero no tiene el diseno requerido. Para

  • 2.5 Figuras Rellenas y Colores 21

    formar la sonrisa en la boca, se retoca la boca. En la lnea 22 se pone el coloramarillo y en la lnea 23 se dibuja un rectangulo que tiene la mitad de alturade la boca, con lo que se borra la mitad superior de la boca, quedando solola mitad inferior visible. Para crear una mejor sonrisa la lnea 24 dibuja otraelipse para cubrir ligeramente la parte superior de la boca.

    1 // PruebaCaraSonriente

    2 // Probar aplicacion que muestra cara sonriente

    3

    4 import javax.swing.JFrame;

    5

    6 public class PruebaCaraSonriente {

    7

    8 public static void main( String args[] ) {

    9 CaraSonriente panel = new CaraSonriente();

    10 JFrame aplicacion = new JFrame();

    11 aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    12 aplicacion.add( panel );

    13 aplicacion.setSize( 230, 250 );

    14 aplicacion.setVisible( true );

    15 } // fin de main

    16 } // fin de la clase PruebaCaraSonriente

    La clase PruebaCaraSonriente, codigo de arriba, crea y muestra unJFrame conteniendo el dibujo. Cuando el JFrame es mostrado, el sistemallama al metodo paintComponent para dibujar la cara sonriente.

    2.5.1. Ejercicios

    1. Usando el metodo fillOval, dibujar una diana que alterne entre doscolores 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 figuras rellenas aleatorias en colo-res, posiciones y tamanos aleatorios. El metodo paintComponent de-bera contener un ciclo que itere 10 veces. En cada iteracion, el ciclodebera determinar si dibuja un rectangulo relleno o una elipse, crearun color aleatorio y escoger coordenadas y dimensiones aleatorias. Lascoordenadas deberan escogerse basadas en el ancho y alto del panel.Longitudes de los lados deberan limitarse a la mitad del ancho y altode la ventana.

  • 22 Caso de estudio

    2.6. Dibujo de Arcos

    Usando las caractersticas graficas de Java, se pueden crear dibujos mascomplejos que seran mas tediosos codificar lnea por lnea. En el siguientecodigo se emplean arreglos y sentencias de repeticion para dibujar un arco iris,ver figura 2.2, usando el metodo fillArc de la clase Graphics. El dibujado dearcos es similar al dibujado de elipses un arco es simplemente una seccionde una elipse.

    Figura 2.2: Dibujo de un arco iris empleando drawArc

    1 // DibujaArcorIris.java

    2 // Se muestra el uso de colores en un arreglo.

    3 import java.awt.Color;

    4 import java.awt.Graphics;

    5 import javax.swing.JPanel;

    6

    7 class DibujaArcoIris extends JPanel {

    8

    9 // Definir el color ndigo y violeta

    10 final Color VIOLETA = new Color( 128, 0, 128 );

    11 final Color INDIGO = new Color( 75, 0, 130 );

    12

    13 // Colores para el arco iris, iniciando con el mas interno.

    14 // Las dos entradas en blanco dan un arco vaco en el centro

    15 private Color colores[] = {

    16 Color.WHITE, Color.WHITE, VIOLETA, INDIGO, Color.BLUE,

    17 Color.GREEN, Color.YELLOW, Color.ORANGE, Color.RED

    18 };

    19

    20 // constructor

    21 public DibujaArcoIris() {

  • 2.6 Dibujo de Arcos 23

    22 setBackground( Color.WHITE ); // fijar el fondo a blanco

    23 } // fin del constructor DibujaArcoIris

    24

    25 // dibujar un arco iris usando crculos concentricos

    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 mas 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 metodo paintComponent

    45 } // fin de la clase DibujaArcoIris

    El codigo anterior inicia con las sentencias import usuales para crear losdbujos, lneas 35. Las lneas 1011 declaran y crean dos nuevos coloresVIOLETA e INDIGO. Para los colores del arco iris en la clase Color se en-cuentran definidos los primeros 5 de los 7 colores del arco iris. En las lneas1517 se inicializa un arreglo con los colores del arco iris, iniciando primerocon los arcos mas internos. El arreglo inicia con dos elementos Color.WHITE,los cuales son para dibujar los arcos vacos en el centro del arco iris. El cons-tructor de las lneas 2123 contiene una sola sentencia que llama al metodosetBackground, el cual se hereda desde la clase JPanel, con el parametroColor.White. El metodo setBackground toma un solo argumento tipo Colory fija el fondo del componente a ese color.

    En la lnea 29 se declara la variable local radio, la cual determina elradio de cada arco. Las variables locales centroX y centroY, lneas 3233,determinan la localidad del punto medio en la base de la ventana. El ciclo enlas lneas 3643 usa la variable de control i para contar hacia atras a partirdel final del arreglo, dibujando los arcos mas grandes primero y colocandoarcos mas pequenos sucesivante al frente del previo. En la lnea 38 se fija el

  • 24 Caso de estudio

    color para dibujar el arco actual desde el arreglo.El metodo fillArc usado en las lneas 4142 dibuja un semicrculo lleno.

    Este metodo requiere seis parametros. Los primeros cuatro representan elrectangulo acotador en el cual el arco sera dibujado. Los primeros dos deestos indican las coordenadas de la esquina superior izquierda del rectanguloacotador, y los siguientes dos indican el ancho y alto. El quinto parametroes el angulo inicial en la elipse, y el sexto indica el barrido, o la cantidad dearco a cubrir. El angulo inicial y de barrido estan medidos en grados, concero grados apuntando a la derecha. Un barrido positivo dibuja el arco ensentido contrario a las manecillas, mientras uno negativo dibuja en el sentidode las manecillas. Un metodo similar a fillArc es drawArc este requierelos mismos parametros como fillArc, pero dibuja la arista del arco en vezde llenarlo.

    1 // PruebaDibujaArcoIris.java

    2 // Aplicacion de prueba para mostrar un arco iris.

    3

    4 import javax.swing.JFrame;

    5

    6 public class PruebaDibujaArcoIris {

    7

    8 public static void main( String args[] ) {

    9 DibujaArcoIris panel = new DibujaArcoIris();

    10 JFrame aplicacion = new JFrame();

    11 aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    12 aplicacion.add( panel );

    13 aplicacion.setSize( 400, 250 );

    14 aplicacion.setVisible( true );

    15 } // fin del main

    16 } // fin de la clase PruebaDibujaArcoIris

    La clase PruebaDibujaArcoIris, codigo anterior, crea y configura unJFrame para mostrar el arco iris. Una vez que el programa hace al panel visi-ble, el sistema llama al metodo paintComponent de la clase DibujaArcoIrispara dibujar el arco iris en la pantalla.

    2.6.1. Ejercicios

    1. En el ejercicio, se dibujaran espirales, ver figura 2.3, con los metodosdrawLine y drawArc. Las espirales deberan cubrir todo el panel, nodebe haber zonas sin llenar al redimensionar la ventana.

  • 2.7 Usando objetos con graficas 25

    a) Dibujar una espiral cuadrada centrada en el panel, usando el meto-do drawLine. Una tecnica es usar un ciclo que incremente la lon-gitud de la lnea despues de dibujar la segunda lnea. La direccionpara dibujar la siguiente linea debera seguir un patron, como aba-jo, izquierda, arriba, derecha.

    b) Dibujar una espiral circular usando el metodo drawArc para dibu-jar un semicrculo cada vez. Cada semicrculo sucesivo debera te-ner un radio mayor y debera continuar dibujando donde el se-micrculo previo termino.

    Figura 2.3: Dibujo de espirales usando drawLine y drawArc

    2.7. Usando objetos con graficas

    Los ejemplos que se han revisado hasta ahora no varan cada vez que seejecuta el programa. Sin embargo, en el segundo ejercicio de la subseccion2.5.1 se pide crear un programa que genera figuras y colores de manera alea-toria. En aquel ejercicio, el dibujo cambia cada vez que el sistema llama apaintComponent para redibujar la pantalla. Para crear un dibujo mas con-sistente que permanezca igual cada vez que es dibujado, se debe guardar lainformacion acerca de las figuras mostradas para que se puedan reproducirde forma exacta cada vez que el sistema llame a paintComponent.

  • 26 Caso de estudio

    Para realizar lo anterior, se creara un conjunto de clases de figuras queguardaran informacion acerca de cada figura. Se haran estas clases inteli-gentes permitiendo que objetos de estas clases dibujarse a si mismo si seproporciona un objeto Graphics. En el codigo que aparace enseguida, la claseMiLinea tiene todas las capacidades indicadas.

    La clase MiLinea importa las clases Color y Graphics en las lneas 34.Las lneas 812 declaran variables de instancia para las coordenadas nece-sarias para dibujar una lnea, y la lnea 12 declara la variable de instanciaque guarda el color de la lnea. El constructor en las lneas 1521 toma cincoparametros, uno para cada variable de instancia que se inicializara. El meto-do dibujar en las lneas 2427 necesita un objeto Graphics que es usadopara dibujar la lnea en el color y las coordenadas apropiadas.

    1 // MiLinea.java

    2 // Declaracion de la clase MiLinea

    3 import java.awt.Color;

    4 import java.awt.Graphics;

    5

    6 public class MiLinea {

    7

    8 private int x1; // coordenada en x del primer extremo

    9 private int y1; // coordenada en y del primer extremo

    10 private int x2; // coordenada en x del segundo extremo

    11 private int y2; // coordenada en y del segundo extremo

    12 private Color miColor; // color de esta figura

    13

    14 // constructor con valores de entradas

    15 public MiLinea( int x1, int y1, int x2, int y2, Color color ) {

    16 this.x1 = x1; // poner el valor en x del primer extremo

    17 this.y1 = y1; // poner el valor en y del primer extremo

    18 this.x2 = x2; // poner el valor en x del segundo extremo

    19 this.y2 = y2; // poner el valor en y del segundo extremo

    20 miColor = color; // poner el color

    21 } // fin del constructor MiLinea

    22

    23 // Dibujar la lnea en el color indicado

    24 public void dibujar( Graphics g ) {

    25 g.setColor( miColor );

    26 g.drawLine( x1, y1, x2, y2 );

    27 } // fin del metodo dibujar

    28 } // fin de la clase MiLinea

    A continuacion se declara la clase DibujaPanel.java, la cual generara ob-jetos aleatorios de la clase MiLinea. La lnea 11 declara un arreglo MiLinea

  • 2.7 Usando objetos con graficas 27

    para guardar las lneas a dibujar. Dentro del constructor, lneas 1435, en lalnea 15 se fija el color del fondo a Color.WHITE. La lnea 17 crea el arreglocon una longitud aleatoria entre 5 y 9. El ciclo, en las lneas 2034 crea unnuevo MiLinea para cada elemento en el arreglo. Las lneas 2225 generancoordenadas aleatorias para cada los extremos de cada lnea, en las lneas2830 se genera un color aleatorio para la lnea. En la lnea 33 se crea unnuevo objeto MiLinea con los valores generados aleatoriamente y se guardaeste en el arreglo.

    El metodo paintComponent itera con los objetos MiLinea en el arre-glo lineas usando una version mejorada del ciclo for, lneas 4142. Cadaiteracion llama el metodo dibujar del objeto actual MiLinea y le pasa el ob-jeto Graphics para dibujarlo en el panel. La clase PruebaDibujo, siguientecodigo, configura una nueva ventana para mostrar el dibujo. Como se estanfijando las coordenadas para las lneas solamente una vez en el constructor,el dibujo no cambia si paintComponent es llamado para refrescar el dibujadoen la pantalla.

    1 // DibujaPanel.java

    2 // Programa que usa la clase MiLinea

    3 // para dibujar lneas aleatorias

    4 import java.awt.Color;

    5 import java.awt.Graphics;

    6 import java.util.Random;

    7 import javax.swing.JPanel;

    8

    9 public class DibujaPanel extends JPanel {

    10 private Random numerosAleatorios = new Random();

    11 private MiLinea lineas[]; // arreglo de lneas

    12

    13 // constructor, crea un panel con figuras aleatorias

    14 public DibujaPanel() {

    15 setBackground( Color.WHITE );

    16

    17 lineas = new MiLinea[ 5 + numerosAleatorios.nextInt( 5 ) ];

    18

    19 // crear lneas

    20 for ( int i = 0; i < lineas.length; i++ ) {

    21 // generar numeros aleatorios

    22 int x1 = numerosAleatorios.nextInt( 300 );

    23 int y1 = numerosAleatorios.nextInt( 300 );

    24 int x2 = numerosAleatorios.nextInt( 300 );

    25 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 lnea a la lista de lneas que seran 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 lneas

    41 for ( MiLinea linea : lineas )

    42 linea.dibujar( g );

    43 } // fin del metodo paintComponent

    44 } // fin de la clase DibujaPanel

    1 // PruebaDibuja.java

    2 // Aplicacion de prueba para mostrar un DibujaPanel.

    3

    4 import javax.swing.JFrame;

    5

    6 public class PruebaDibujo {

    7

    8 public static void main( String args[] ) {

    9

    10 DibujaPanel panel = new DibujaPanel();

    11 JFrame application = new JFrame();

    12

    13 application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    14 application.add( panel );

    15 application.setSize( 300, 300 );

    16 application.setVisible( true );

    17 } // fin de main

    18 } // fin de la clase PruebaDibujo

    2.7.1. Ejercicios

    1. Extender el programa de esta seccion para dibujar aleatoriamente rectangu-los y elipses. Crear las clases MiRectangulo y MiElipse. Ambas clasesdeberan incluir coordenadas x1, y1, x2, y2, un color y un valor boo-

  • 2.7 Usando objetos con graficas 29

    leano para determinar si la figura es rellena. Declarar un constructoren cada clase con argumentos para inicializar todas las variables deinstancia. Para ayudar a dibujar rectangulos y elipses, cada clase de-bera dar metodos getSuperiorIzquierdaX, getSuperiorIzquierdaY,getAncho y getAlto que calculen la coordenada superior izquierda x,la coordenada superior izquierda y, el ancho y el alto, respectivamen-te. La coordenada superior izquierda x, es el valor mas pequeno de lasdos coordenadas x, de manera similar para la coordenada superior y,el ancho es el valor absoluto de la diferencia entre las abscisas, y laaltura es el valor absoluto de la diferencia entre las dos ordenadas delos extremos.

    La clase DibujaPanel, la cual extiende a JPanel, maneja la creacionde las figuras, debera declarar tres arreglos, uno para cada forma defigura. La longitud de cada arreglo debera ser un numero aleatorio entre1 y 5. El constructor de la clase DibujaPanel llenara cada uno de losarreglos con figuras de posicion, tamano, color y llenado aleatorio, comose indica en el ejercicio 2 de la seccion 2.5.1.

    Adicionalmente, modificar las tres clases de figuras para incluir lo si-guiente:

    a) Un constructor sin argumentos que fija todas las coordenadas dela figura a cero, el color de la figura a color negro, y la propiedad dellenado a false, esto ultimo solo para MiRectangulo y MiElipse.

    b) Metodos set para las variables de instancia en cada clase. Losmetodos que fijen un valor coordenado deberan verificar que elargumento es mayor que, o igual a cero antes de fijar la coordenada si no, estos deberan poner la coordenada a cero. El constructordebera llamar a los metodos set en vez de inicializar las variablesde instancia directamente.

    c) Metodos get para las variables de instancia en cada clase. El meto-do dibujar debera referenciar las coordenadas por los metodos geten vez de acceder directamente a las variables.

  • 30 Caso de estudio

    2.8. Texto e imagenes con etiquetas

    Los programas frecuentemente usan etiquetas cuando requieren mostrarinformacion o instrucciones al usuario en una interfaz grafica. Las etiquetasson una forma conveniente para identificar componentes GUI en la pantallay para mantener informado al usuario respecto al estado actual del progra-ma. En Java, un objeto de la clase JLabel del paquete javax.swing puedemostrar una sola lnea de texto, una imagen o ambos. El siguiente ejemplomuestra varias caractersticas de JLabel.

    1 // LabelDemo.java

    2 // Muestra el uso de etiquetas

    3 import java.awt.BorderLayout;

    4 import javax.swing.ImageIcon;

    5 import javax.swing.JLabel;

    6 import javax.swing.JFrame;

    7

    8 public class LabelDemo {

    9

    10 public static void main( String args[] ) {

    11 // crear una etiqueta plana con texto

    12 JLabel etiquetaNorte = new JLabel( "Norte" );

    13

    14 // crear un icono desde una imagen para ponerlo en un JLabel

    15 ImageIcon iconoEtiqueta = new ImageIcon( "gnome-gnibbles.png" );

    16

    17 // crear una etiqueta con un icono en vez de texto

    18 JLabel etiquetaCentro = new JLabel( iconoEtiqueta );

    19

    20 // crear otra etiqueta con un icono

    21 JLabel etiquetaSur = new JLabel( iconoEtiqueta );

    22

    23 // configurar etiqueta para mostrar texto, al igual que el icono

    24 etiquetaSur.setText( "Sur" );

    25

    26 // crear una ventana para poner las etiquetas

    27 JFrame aplicacion = new JFrame();

    28

    29 aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    30

    31 // agregar las etiquetas a la ventana, el segundo argumento indica

    32 // en que lugar de la ventana se pondra la etiqueta

    33 aplicacion.add( etiquetaNorte, BorderLayout.NORTH );

    34 aplicacion.add( etiquetaCentro, BorderLayout.CENTER );

  • 2.8 Texto e imagenes 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 lneas 36 se importan las clases que se requieren para mostrar lasetiquetas. BorderLayout del paquete java.awt tiene constantes para indicardonde se pueden colocar componentes GUI en un JFrame. La clase ImageIconrepresenta una imagen que puede ser mostrada en un JLabel, y la claseJFrame representa la ventana que contendra todas las etiquetas.

    La lnea 12 crea un JLabel que muestra su argumento para el constructorla cadena "Norte". La lnea 15 declara la variable local iconoEtiquetay le asigna un nuevo ImageIcon. El constructor para ImageIcon recibe unacadena que indica el camino a la imagen. Como solamente se indica un nom-bre de archivo, Java supone se encuentra en el mismo directorio de la cla-se LabelDemo. ImageIcon puede cargar imagenes en formato GIF, JPEG yPNG. La lena 18 declara e inicializa la variable local etiquetaCentro conun JLabel que muestra a iconoEtiqueta. Sin embargo, en la lnea 24 sellama al metodo setText para cambiar el texto que la etiqueta muestra. Elmetodo setText puede ser llamado por cualquier JLabel para cambiar sutexto. Este JLabel mostrara el icono y el texto.

    En la lnea 27 se crea un JFrame que mostrara los JLabels, y la lnea29 indica que el programa debera terminar cuando el JFrame se cierre. Seponene las etiquetas en la ventana en las lneas 3335 llamando una versionsobrecargada del metodo add que toma dos parametros. El primer metodo esel componente que se quiere poner, y el segundo es la region en la cual estedebera ser puesto. Cada JFrame tiene asociado un manejador que ayuda enla posicion de los componentes que tiene puestos. El manejado por defectopara 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 esta declarado como una constante enla clase BorderLayout. Cuando se llama al metodo add con un argumento,el JFrame coloca al componente usando CENTER automaticamente. Si unaposicion ya contena un componente, entonces el nuevo componente toma sulugar. En las lneas 27 y 39 se pone el tamano de la ventana y se hace visibleen pantalla.

  • 32 Caso de estudio

    2.8.1. Ejercicio

    1. Modificar el ejercicio 1 de la seccion 2.7.1 para incluir un JLabel comouna barra de estado que muestre la cantidad de cada figura dibujada,podra tener un texto como: Lneas 3, Elipses 2, Rectangulos 4 . Laclase DibujaPanel debera declarar un metodo que regrese una cadenaconteniendo el texto del estado. En el metodo main, primero crear elDibujaPanel, despues crear el JLabel con el texto del estado comoun argumento del constructor JLabel. Poner el JLabel en la regioninferior de la ventana.

    2.9. Dibujado con polimorfismo

    Como se puede observar en el ejercicio 1 de la seccion 2.7.1, y en lamodificacion solicitada en el ejercicio 1 de la seccion 2.8.1 existen muchassimilaridades entre las clases de las figuras. Usando herencia se pueden fac-torizar las caractersticas comunes de las tres clases y colocarlas en una solasuperclase. Se pueden entonces manipular los todos los objetos, de tres tiposde figuras, polimorficamente usando variables del tipo de la superclase. Re-moviendo la redundancia en el codigo resultara un programa mas pequeno yflexible que es mas facil de mantener.

    2.9.1. Ejercicios

    1. Modificar las clases MiLinea, MiElipse y MiRectangulo del ejerciciouno de la seccion 2.7.1 y 2.8.1 para crear la siguiente jerarqua de clases:

    La clase MiFigura es una subclase de java.lang.Object

    Las clases MiLinea, MiElipse y MiRectangulo son subclases deMiFigura.

    Las subclases de la jerarqua MiFigura deberan ser clases figura inte-ligentes para saber como dibujarse ellas si se proporciona un objetoGraphics que les diga donde dibujar. Una vez que el programa cree unobjeto de la jerarqua, este lo puede manipular polimorficamente porel resto de su existencia como un MiFigura.

    En la solucion, la clase MiFigura debera ser abstract. Como MiFigurarepresenta cualquier figura en general, no se puede implementar el

  • 2.9 Dibujado con polimorfismo 33

    metodo dibujar sin saber exactamente que figura es. Los datos re-presentando las coordenadas y el color de las figuras en la jerarquadeberan ser declarados como miembros private de la clase MiFigura.Ademas de los datos comunes, la clase MiFigura debera declarar lossiguientes metodos:

    a) Un constructor sin argumentos que ponga todas las coordenadasde la figura en cero y el color en negro.

    b) Un constructor que inicialize las coordenadas y el color con losvalores de los argumentos proporcionados.

    c) Metodos set para las coordenadas individuales y el color que per-mitan al programador poner cualquier parte de los datos indepen-dientemente para una figura en la jerarqua.

    d) Metodos get para las coordenadas individuales y el color que per-mitan al programador recuperar cualquier parte de los datos in-dependientemente para una figura en la jerarqua.

    e) El metodo abstract

    public abstract void dibujar( Graphics g );

    el cual sera llamado por el metodo paintComponent del programapara dibujar una figura en la pantalla.

    Para asegurar la encapsulacion, todos los datos en la clase MiFiguradeberan ser private. Esto requiere declarar metodos set y get para ma-nipular los datos. La clase MiLinea debera proporcionar un constructorsin argumentos y un constructor con argumentos para las coordenadasy el color. Las clases MiElipse y MiRectangulo deberan proporcionarun constructor sin argumentos y un constructor con argumentos paralas coordenadas, el color y para saber si la figura es rellena. El cons-tructor sin argumentos debera, adicionalmente de poner los valores pordefecto, fijar la figura sin relleno.

    Se pueden dibujar lneas, rectangulos, y elipses si se conocen dos pun-tos en el plano. Las lneas requieren las coordenadas x1, y1, x2 y y2.El metodo drawLine de la clase Graphics conectara los dos puntosdados con un lnea. Si se tienen los mismos cuatro valores para elipsesy rectangulos, se pueden calcular los argumentos necesarios para dibu-jarlos. Cada uno requiere el valor x de la esquina superior izquierda

  • 34 Caso de estudio

    (el mas pequeno de las x de las dos abscisas), y de la esquina superiorizquierda (el mas pequeno de las y de las dos ordenadas), un ancho (elvalor absoluto de la diferencia de las dos abscisas) y un alto (el valorabsoluto de la diferencia de las dos ordenadas). Los rectangulos y laselipses podran tambien tener una bandera relleno que determine sise dibuja la figura como rellena.

    No debera haber en el programa variables MiLinea, MiRectangulo,o MiElipse solamente variables MiFigura que contengan referen-cias a objetos tipo MiLinea, MiRectangulo, o MiElipse. El programadebera generar figuras aleatorias y guardarlas en un arreglo del tipoMiFigura. El metodo paintComponent debera recorrer el arreglo tipoMiFigura y dibujar cada figura (es decir, llamando polimorficamenteal metodo dibujar de cada figura.

    Permitir al usuario indicar, con un cuadro de dialogo de entrada, elnumero de figuras que se generaran. El programa entonces las generay las muestra con una barra de estado que informa al usuario cuantasfiguras de cada una fueron creadas.

    2. En el ejercicio 1, se creo una jerarqua MiFigura en donde las clasesMiLinea, MiRectangulo y MiElipse extienden directamente a MiFigura.Si la jerarqua fue disenada adecuadamente, se podra observar las simi-laridades entre las clases MiRectangulo y MiElipse. Redisenar y reim-plementar el codigo para las clases MiRectangulo y MiElipse para fac-torizar las caractersticas comunes en la clase abstracta MiFiguraAcotadapara generar la siguiente jerarqua.

    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 debera declarar dos constructores que imi-ten a los de la clase MiFigura y que agreguen un parametro para ponersi la figura es rellena. La clase MiFiguraAcotada debera tambien decla-rar metodos set y get para manipular el campo relleno y metodos quecalculen la coordenada x de la esquina superior izquierda, la coordena-da y de la esquina superior izquierda, el ancho y el alto. Si esta biendisenado, las nuevas clases MiElipse y MiRectangulo deberan tenercada una dos constructores y un metodo dibujar.

  • Captulo 3

    Componentes GUI

    3.1. Introduccion

    Una interfaz grafica de usuario GUI (graphical user interface) presentaun mecanismo amigable al usuario para interactuar con una aplicacion. UnaGUI da a una aplicacion una apariencia y comportamiento.

    Las GUI estan construdas con componentes GUI. Estos algunas vecesson llamados controles o widgetsabreviatura de window gadgetenotros lenguajes. Un componente GUI es un objeto con el cual el usuariointeractua usando el raton, el teclado u otra forma de entrada, como el reco-nocimiento de voz.

    3.2. Generalidades de Componentes Swing

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

  • 36 Componentes GUI

    Componente DescripcionJLabel Muestra texto o iconos no editables.JTextField Permite al usuario ingresar datos desde

    el teclado. Puede tambien ser usado paramostrar texto editable o no editable.

    JButton Dispara un evento cuando se pulsa conel raton.

    JCheckBox Indica una opcion que puede ser o no se-leccionada.

    JComboBox Da una lista de artculos que abren haciaabajo (drop-down) de las cuales el usua-rio puede hacer una seleccion pulsandosobre un artculo o posiblemente teclean-do en el cuadro.

    JList Da una lista de artculos de los cualesel usuario puede hacer una seleccion pul-sando en cualquier artculo en la lista.Elementos multiples pueden ser seleccio-nados.

    JPanel Da una area en la cual los componen-tes pueden ser colocados y organizados.Puede tambien ser usado como area dedibujo para graficas.

    Varios componentes Swing son componentes puros de Java estan escri-tos, manipulados y desplegados completamente en Java. Estos son parte deJFC (Java Foundation Classes) bibliotecas de Java para desarrollo GUIde plataforma cruzada.

    Swing vs. AWT. Hay actualmente dos conjuntos de componentes GUI enJava. Antes de que Swing fuera introducido en Java SE 1.2, la GUI de Ja-va era construida con componentes de AWT del paquete java.awt. Cuandouna aplicacion Java con un GUI de AWT se ejecuta en diferentes platafor-mas JAVA, los componentes de la aplicacion GUI se muestran diferentes encada plataforma. Por ejemplo, una aplicacion que muestre un objeto del tipoButton del paquete java.awt, en un computadora que ejecute el sistema ope-rativo Windows, el boton tendra la misma apariencia de los botones de otrasaplicaciones para ese sistema, es decir, los componentes se veran, para algun

  • 3.2 Generalidades de Componentes Swing 37

    sistema operativo grafico, como los componentes de las otras aplicaciones.Por otra parte, la forma en la cual un usuario interactua con un componenteAWT difiere entre plataformas.

    Los componentes GUI de Swing permiten especificar un look-and-feel (laapariencia y la forma en la cual el usuario interacciona con la aplicacion)uniforme para la aplicacion para todas las plataformas o usar de cada pla-taforma el look-and-feel de la plataforma. Una aplicacion puede cambiar suapariencia durante la ejecucion para permitir al usuario escoger su aparienciapreferida.

    Componentes peso ligero vs peso pesado. Muchos componentes Swingno estan empatados a los componentes GUI soportados por la plataformasubyacente en la cual la aplicacion se ejecuta. Tales componentes GUI sonconocidos como componentes de peso ligero o lightweight. Los componentesAWT, muchos son paralelos a los componentes Swing, estan empatados a laplataforma local y son llamados componentes de peso pesado o heavyweight,porque descansan en la plataforma local del sistema de ventanas para deter-minar su funcionalidad y su apariencia.

    Varios componentes Swing son componentes pesados. Parecidos a los com-ponentes AWT, los componentes GUI pesados de Swing requieren interacciondirecta con el sistema de ventanas local, lo cual podra restringir su aparienciay funcionalidad, haciendolos menos flexibles que los componentes ligeros.

    Superclases de los componentes ligeros La clase Object es la super-clase de la jerarqua de clases de Java.

    La clase Component del paquete java.awt es una subclase de Objectque declara varios atributos y comportamientos comunes a los componentesGUI en los paquetes java.awt y javax.swing. Muchos componentes GUIextienden 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 loscomponentes pueden ser organizados y mostrados en la pantalla. Cualquierobjeto, que es del tipo Container, puede ser usado para organizar otrosComponents en una GUI. Como un Container es un Component, se puedenadjuntar 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 unasubclase de Container, todos los componentes ligeros de Swing son tam-bien Container. Algunas caractersticas comunes de los componentes ligerossoportadas por JComponent incluyen:

    1. Un look-and-feel enchufable que puede ser usado para configurar laapariencia de componentes.

    2. Accesos rapidos de teclado, llamados nemotecnicos, para el acceso di-recto a los componentes GUI a traves del teclado.

    3. Capacidades comunes de manejo de eventos para casos donde varioscomponentes GUI inician las mismas acciones en una aplicacion.

    4. Breves descripciones del proposito de los componentes GUI, llamadossugerencias (tool tips), que son mostrados por un perodo corto cuandoel cursor del raton es posicionado sobre el componente.

    5. Soporte para tecnologas asistentes, tales como lectores braille para losimpedidos visualmente.

    6. Soporte para localizacion de interfaz-usuario esto es, configurar lainterfaz del usuario para mostrar en diferentes lenguas y convencionesculturales locales.

    3.3. Mostrar texto e imagenes en una venta-

    na

    Se presenta en el siguiente ejemplo un framework (marco) para construiraplicaciones GUI. El framework usa varios conceptos que se veran en variasaplicaciones GUI. Este es el primer ejemplo en el cual la aplicacion apareceen su propia ventana. Muchas ventanas que se crearan seran una instancia dela clase JFrame o una subclase de JFrame. JFrame proporciona los atributosbasicos y comportamientos de una ventana una barra de ttulo en la partesuperior de la ventana, y botones para minimizar, maximizar, y cerrar laventana. Como una aplicacion GUI es tpicamente especifica a la aplicacion,varios de los ejemplos consistiran de dos clases una subclase de JFrameque ayuda a mostrar nuevos conceptos GUI y una clase aplicacion en la cualmain crea y muestra la ventana primaria de la aplicacion.

  • 3.3 Mostrar texto e imagenes en una ventana 39

    Una GUI tpica consiste de varios componentes. En un GUI grande pue-de ser difcil identificar el proposito de cada componente a menos que eldisenador de la GUI proporcione instrucciones de texto o informacion in-dicando el proposito de cada componente. Tal texto es conocido como unaetiqueta y es creado con la clase JLabel una subclase de JComponent. UnJLabel muestra una lnea de texto de solo lectura, una imagen, o ambas.Las aplicaciones raramente cambian el contenido de una etiqueta despues dehaberla creado.

    La aplicacion VentanaLabel muestra varias capacidades de JLabel ymuestra el marco que sera usado en la mayora de los ejemplos GUI. Haymuchas mas caractersticas de cada componente GUI que las vistas en losejemplos. Para revisar los detalles completos de cada componente GUI, serecomienda revisar la documentacion.

    La clase VentanaLabel, que se muestra a continuacion, es una subclasede JFrame. Se usara una instancia de la clase VentanaLabel para mostraruna ventana conteniendo tres JLabels. Las lneas 49 importan las clasesusadas en la clase VentanaLabel. La clase extiende a JFrame para heredarlas caractersticas de una ventana. Las lneas 1315 declaran las variablesde instancias de las tres JLabel, cada una de las cuales es instanciada en elconstructor de VentanaLabel en las lneas 1843. Tpicamente, el constructorde la subclase del JFrame construye la GUI que es mostrada en la ventanacuando la aplicacion se ejecuta. La lnea invoca al constructor de la superclaseJFrame con el argumento "Probando JLabel". El constructor de JFrameemplea el String como el texto de la barra de ttulos de la ventana.

    1 // VentanaLabel.java

    2 // Demostracion de la clase JLabel.

    3

    4 import java.awt.FlowLayout; // indica como los componentes son arreglados

    5 import javax.swing.JFrame; // proporciona capacidades basicas de ventana

    6 import javax.swing.JLabel; // muestra texto e imagenes

    7 import javax.swing.SwingConstants; // constantes comunes usadas con Swing

    8 import javax.swing.Icon; // interfaz usada para manipular imagenes

    9 import javax.swing.ImageIcon; // carga imagenes

    10

    11 public class VentanaLabel extends JFrame {

    12

    13 private JLabel etiq1; // JLabel con solo texto

    14 private JLabel etiq2; // JLabel construda con texto e icono

    15 private JLabel etiq3; // JLabel con texto e icono agregado

    16

  • 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 // PruebaLabel.java

    2 // Probador de VentanaLabel.

    3

    4 import javax.swing.JFrame;

    5 public class PruebaLabel {

    6

    7 public static void main( String args[] ) {

    8

    9 VentanaLabel ventanaLabel = new VentanaLabel(); // crear VentanaLabel

    10 ventanaLabel.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    11 ventanaLabel.setSize( 275, 180 ); // fijar el tama~no de la ventana

    12 ventanaLabel.setVisible( true ); // mostrar la ventana

    13 } // fin de main

    14 } // fin de la clase PruebaLabel

  • 3.3 Mostrar texto e imagenes en una ventana 41

    Indicando el diseno Cuando se construye una GUI, cada componenteGUI debera estar adjuntado a un contenedor, tal como una ventana creadacon un JFrame. Tambien, el programador debera decidir donde posicionarcada componente GUI. Esto es conocido como especificar el diseno de loscomponentes GUI. Java proporciona varios manejadores de diseno que pue-den ayudar a colocar los componentes.

    Varios ambientes integrados de desarrollo o IDEs (Integrated DevelopmentEnvironment) dan herramientas de diseno GUI, en las cuales se puede indicarel tamano exacto y lugar de un componente de forma visual empleando elraton, entonces el IDE generara el codigo GUI por el usuario. Con los IDEs sepuede simplificar la creacion del GUI, sin embargo cada uno tiene diferentescapacidades.

    Para los ejemplos que se revisaran, se usaran los manejadores de disenode Java. Uno de estos manejadores de diseno es FlowLayout, en el cual loscomponentes GUI son colocados en un contenedor de izquierda a derecha enel orden en el cual el programa los agrega al contenedor. Cuando no hay masespacio para meter componentes de izquierda a derecha. los componentesse continuan mostrando de izquierda a derecha en la siguiente lnea. Si elcontenedor es redimensionado, un FlowLayout redimensiona los componentespara acomodarlos al nuevo ancho del contenedor, posiblemente con menos omas renglones de componentes GUI. El metodo setLayout es heredado en laclase VentanaLabel indirectamente desde la clase Container. El argumentoal metodo debera ser un objeto de una clase que implementa la interfazLayoutManager, por ejemplo FlowLayout. En la lnea 20 se crea un nuevoobjeto FlowLayout y se pasa su referencia como argumento a setLayout

    Creacion y pegado de etiquetas Una vez que se ha indicado el diseno dela ventana, se puede inciar creando y pegando componentes GUI a la ventana.Las lneas 23, 30, 31 crean objetos JLabel que pasan diferentes referencias yconstantes a los constructores. En la lnea 35 se usa un constructor JLabel sinargumentos, pero posteriormente se indica el texto y el icono con los metodossetText y setIcon respectivamente, como se muestra en las lneas 36 y 38.En las lneas 24, 32 y 41 se usa el metodo setToolTipText (heredado porJLabel desde JComponent para indicar la sugerencia que es mostrada cuandoel usuario pone el cursor del raton sobre el JLabel en el GUI.

    En la lnea 29, la expresion getClass().getResource("gnome-gnibbles-.png") llama al metodo getClass (heredado desde la clase Object) pa-

  • 42 Componentes GUI

    ra recuperar una referencia al objeto Class que representa la declaracionde la clase VentanaLabel. Esa referencia es entonces usada para llamar almetodo getResource de Class, la cual regresa la localidad de la imagencomo un URL (uniform resource locator). El constructor ImageIcon usa elURL para localizar la imagen, y entonces cargarla en memoria. El carga-dor de clases sabe donde cada clase que se carga esta localizada en disco.El metodo getResource usa el cargador de clases del objeto Class paradeterminar el lugar de un recurso, tal como una archivo de imagen. Eneste ejemplo, el archivo de imagen esta guardado en el mismo lugar queel archivo VentanaLabel.class. La tecnica descrita permite a una aplica-cion cargar archivos de imagen desde localidades que son relativas al archivoVentanaLabel.class en el disco.

    Como se puede apreciar en la lnea 30, al crear un JLabel se puede pasaren el constructor una referencia tipo Icon para que la etiqueta este compuestade texto e imagen. Tambien es posible, que despues de haber creado el objeto,se agregue la imagen, usando el metodo setIcon, como se hace en la lnea28.

    Las lneas 39 y 40 usan los metodos setHorizontalTextPosition ysetVerticalTextPosition de la clase JLabel para acomodar el texto hori-zontalmente y verticalmente respectivamente. Las constantes empleadas conestos metodos, que se encuentran definidas en la clase SwingConstants sedescriben a continuacion:

    Posicion HorizontalSwingConstants.LEFT Texto a la izquierda.

    SwingConstants.CENTER Texto en el centro.SwingConstants.RIGHT Texto a la derecha.

    Posicion VerticalSwingConstants.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 interactua con una aplicacion GUI para indicarlas tareas que la aplicacion debera hacer. Cuando el usuario interactua con un

  • 3.4 Campos de texto y eventos 43

    componente GUI, la interaccion conocida como un evento conduce alprograma a realizar una tarea. Algunos eventos comunes que podran causarque una aplicacion haga una tarea incluyen el pulsado de un boton, el tecleadoen un campo de texto, la seleccion de un elemento de un menu, el cerradode una ventana y el movimiento del raton. El codigo que realiza una tareaen respuesta a un evento es llamado un manejador de eventos y todo elproceso de respuesta a eventos es conocido como manejo de eventos.

    Se revisan en esta seccion dos nuevos componentes GUI que pueden ge-nerar eventos JTextField y JPasswordField del paquete java.swing. Laclase JTextField extiende la clase JTextComponent del paquete javax.swing-.text, la cual proporciona varias capacidades comunes a los componentesSwing basados en texto. La clase JPasswordField extiende a JTextField yagrega varios metodos que son especficos para procesar contrasenas. Cadauno de estos componentes es una area de una sola lnea en el cual el usua-rio puede ingresar texto usando el teclado. Las aplicaciones pueden tambienmostrar texto en un JTextField. Un JPasswordField muestra que caracte-res han sido tecleado conforme el usuario los ha ingresado, pero esconde elcaracter actual con un caracter eco, asumiendo que estos representan unacontrasena que solo debera ser conocida por el usuario.

    Cuando el usuario teclea datos en un JTextField o en un JPasswordField,y despues presiona Intro, un evento ocurre. El siguiente ejemplo muestra co-mo un programa puede realizar una tarea en respuesta a ese evento. Lastecnicas mostradas en el ejemplo son aplicables a todos los componentesGUI que generan eventos.

    La aplicacion siguiente usa las clases JTextField y JPasswordField paracrear y manipular cuatro campos de texto. Cuando el usuario teclea en unode los campos de texto, y presiona Intro, la aplicacion muestra un cuadrode dialogo conteniendo el texto que el usuario tecleo. El usuario solo puedeteclear en el campo de texto que este en foco. Un componente recibe elfoco cuando el usuario pulsa en el componente. Esto es importante, porqueel campo de texto con el foco es el que genera un evento cuando el usua-rio presiona Intro. En este ejemplo, cuando el usuario presiona Intro en elJPasswordField, la contrasena es revelada.

    1 // VentanaTextField.java

    2 // Mostrando la clase JTextField.

    3

    4 import java.awt.FlowLayout;

    5 import java.awt.event.ActionListener;

  • 44 Componentes GUI

    6 import java.awt.event.ActionEvent;

    7 import javax.swing.JFrame;

    8 import javax.swing.JTextField;

    9 import javax.swing.JPasswordField;

    10 import javax.swing.JOptionPane;

    11

    12 public class VentanaTextField extends JFrame {

    13

    14 private JTextField campoTexto1; // campo de texto con el tama~no dado

    15 private JTextField campoTexto2; // campo de texto construido con texto

    16 private JTextField campoTexto3; // campo de texto con texto y tama~no

    17 private JPasswordField campoContra; // campo de contrase~na con texto

    18

    19 // constructor VentanaTextField que agrega JTextFields al JFrame

    20 public VentanaTextField() {

    21 super( "Probando JTextField y JPasswordField" );

    22 setLayout( new FlowLayout() ); // poner el dise~nador de ventana

    23

    24 // construir campo de texto con 10 columnas

    25 campoTexto1 = new JTextField( 10 );

    26 add( campoTexto1 ); // agregar campoTexto1 al JFrame

    27

    28 // construir campo de texto con texto por defecto

    29 campoTexto2 = new JTextField( "Ingresar texto aqu" );

    30 add( campoTexto2 ); // agregar campoTexto2 al JFrame

    31

    32 // construir campo de texto con texto por defecto y 21 columnas

    33 campoTexto3 = new JTextField( "Campo de texto no editable", 21 );

    34 campoTexto3.setEditable( false ); // deshabilitar la edicio`n

    35 add( campoTexto3 ); // agregar campoTexto3 al JFrame

    36

    37 // construir campo de contrase~na con texto por defecto

    38 campoContra = new JPasswordField( "Texto oculto" );

    39 add( campoContra ); // agregar campoContra al JFrame

    40

    41 // registrar manejadores de eventos

    42 TextFieldHandler manejador = new TextFieldHandler();

    43 campoTexto1.addActionListener( manejador );

    44 campoTexto2.addActionListener( manejador );

    45 campoTexto3.addActionListener( manejador );

    46 campoContra.addActionListener( manejador );

    47 } // fin del constructor VentanaTextField

    48

    49 // clase privada interna para manejo de eventos

    50 private class TextFieldHandler implements ActionListener {

  • 3.4 Campos de texto y eventos 45

    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 presiono Intro en JTextField campoTexto1

    58 if ( evento.getSource() == campoTexto1 )

    59 cadena = String.format( "campoTexto1: %s",

    60 evento.getActionCommand() );

    61

    62 // usuario presiono Intro en JTextField campoTexto2

    63 else if ( evento.getSource() == campoTexto2 )

    64 cadena = String.format( "campoTexto2: %s",

    65 evento.getActionCommand() );

    66

    67 // usuario presiono Intro en JTextField campoTexto3

    68 else if ( evento.getSource() == campoTexto3 )

    69 cadena = String.format( "campoTexto3: %s",

    70 evento.getActionCommand() );

    71

    72 // usuario presiono 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 metodo actionPerformed

    80 } // fin de la clase interna TextFieldHandler

    81 } // fin de la clase VentanaTextField

    1 // PruebaTextField.java

    2 // Probando VentanaTextField.

    3

    4 import javax.swing.JFrame;

    5

    6 public class PruebaTextField {

    7

    8 public static void main( String args[] ) {

    9 VentanaTextField ventanaTextField = new VentanaTextField();

    10 ventanaTextField.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    11 ventanaTextField.setSize( 350, 100 ); // fijar tama~no de la ventana

    12 ventanaTextField.setVisible( true ); // mostrar ventana

    13 } // fin main

    14 } // fin de la clase PruebaTextField

  • 46 Componentes GUI

    Creacion de la GUI. La lnea 22 pone el diseno de VentanaTextFielda FlowLayout. La lnea 25 crea campoTexto1 con 10 columnas de texto. Elancho en pxeles de una columna de texto esta determinado por el anchopromedio de un caracter en el campo de texto de la fuente actual. Cuandoel texto es mostrado en un campo de texto y el texto es mas ancho que elcampo de texto, una porcion del texto en el lado derecho no es visible. Si seesta tecleando en un campo de texto y el cursor alcanza el lado derecho delcampo de texto, el texto del lado izquierdo es recorrido hacia alla y no severa mas. El usuario puede usar las teclas de navegacion izquierda y derechapara moverse a traves del texto completo aun si el texto entero no es visibleen un momento. La lnea 26 agrega campoTexto1 al JFrame.

    La lnea 29 crea campoTexto2 con el texto inicial Ingresar texto aqupara ser mostrado en el campo de texto. El ancho del campo de texto esta de-terminado por el ancho del texto indicado en el constructor. La lnea 30 loagrega al JFrame.

    La lnea 33 crea campoTexto3 y llama al constructor JTextField condos argumentos el texto Campo de texto no editable a mostrar y elnumero de columnas (21). La lnea 34 usa el metodo setEditable (heredadaa JTextField desde la clase JTextComponent) para hacer el campo de textono editable. En la lnea 35 se agrega al JFrame.

    La lnea 38 crea campoContrase~na con el texto Texto oculto paramostrarlo en el campo de texto. Cuando se ejecuta la aplicacion, observarque el texto es mostrado como una cadena de asteriscos. La lnea 39 lo agregaal JFrame.

    Pasos para manejar eventos. El ejemplo debera mostrar un cuadro demensaje conteniendo el texto desde el campo cuando el usuario presiona Introen aquel campo de texto. Antes de que una aplicacion pueda responder a unevento para un componente GUI particular, el programador debera hacervarios pasos de codificacion:

    1. Crear una clase que represente al manejador de evento.

    2. Implementar una interfaz apropiada, conocida como interfaz recep-tora del evento, en la clase del primer paso.

    3. Indicar que un objeto de la clase desde los pasos 1 y 2 debera sernotificado cuando el evento ocurrra. Esto es conocido como registrarel manejador de evento.

  • 3.4 Campos de texto y eventos 47

    Uso de clases anidadas para manejo de eventos. Todas las clases vis-tas previamente son llamadas clases de nivel superior esto es, las clasesno fueron declaradas dentro de otra clase. Java permite declarar clases den-tro de otra estas clases son llamadas clases anidadas. Las clases anidadaspueden ser static o no. Las clases anidadas no static son llamadas clasesanidadas y son frecuentemente empleadas para manejar eventos.

    Una clase interna permite acceso directamente a las variables y metodosde su clase de nivel superior, aun si ellos son private.

    Antes de que un objeto de una clase interna pueda ser creado, debera ha-ber primero un objeto de la clase de nivel superior que contenga la claseinterna. Esto es requerido porque un objeto de la clase interna implcitamen-te tiene una referencia a un objeto de su clase de nivel superior. Hay unarelacion especial entre estos objetos al objeto de la clase interna se le per-mite accesar directamente todas las variables de instancia y metodos de laclase externa. Una clase anidada que es static no requiere un objeto de laclase de nivel superior y no tiene implcitamente una referencia a un objetode la clase de nivel superior.

    El manejo de evento en este ejemplo es hecho por un objeto de la clase in-terna private TextFieldHandler en las lneas 5081. Esta clase es privateporque esta sera usada solamente para crear manejadores de eventos para loscampos de texto en la clase de nivel superior VentanaTextField. Al igual quecon otros miembros de una clase, las clases internas pueden ser declaradaspublic, protected o private.

    Los componentes GUI pueden generar una variedad de eventos en res-puesta a las interacciones del usuario. Cada evento esta representado poruna clase y puede ser procesado solamente por el tipo apropiado de mane-jador de eventos. Los eventos que un componente GUI soporta estan des-critos en la documentacion API de Java. Cuando el usuario presiona Introen un JTextField o un JPasswordField, el componente GUI genera unActionEvent (paquete java.awt.event). Tal evento es procesado por un ob-jeto que implementa la interfaz ActionListener (paquete java.awt.event).Como JPasswordField es una subclase de JTextField, JPasswordField so-porta los mismos eventos.

    Para preparar el manejo de los eventos, la clase interna TextFieldHandlerimplementa la interfaz ActionListener y declara el unico metodo en la in-terfaz actionPerformed (lneas 5080). Este metodo indica las tareas arealizar cuando un evento ActionEvent suceda.

  • 48 Componentes GUI

    Registro del manejador de eventos En el constructor VentanaTextField,la lnea 42 crea un objeto TextFieldHandler y lo asigna a la variable maneja-dor. El metodo actionPerformed del objeto sera llamado automaticamentecuando el usuario presione Intro en cualquiera de los campos de texto GUI.Sin embargo, antes de que esto pueda ocurrir, el programa debera regis-trar este objeto como el manejador de eventos para cada campo de texto.Las lneas 4346 son las sentencias de registro de eventos que indican quemanejador se empleara con los tres JTextField y el JPasswordField. Laaplicacion llama al metodo addActionListener de la clase JTextField, pa-ra regist