Introducci on a componentes...

30
Introducci´ on a componentes Swing H. Tejeda Mayo 2016 ´ Indice 1. Introducci´ on 1 2. Clase JFrame 2 3. Clase JLabel 6 4. Manejador de dise˜ no 9 5. Extensi´ on de la clase JFrame 11 6. Clases de entrada 13 7. Programaci´ on de manejo de eventos 17 8. Receptores de eventos 21 9. Clases para selecci´ on 23 1. Introducci´ on Las aplicaciones son m´ as amigables al usuario cuando estas contienen componentes interfaz de usuario o UI (User Interface ). Los componentes UI son botones, campos de texto, y otros con los cuales el usuario puede interactuar. Los creadores de Java han empacado una cantidad de componentes preescritos en el paquete Swing. Los componentes Swing son elementos UI tales como cuadros de di´ alogo y botones; se reconocen porque sus nombres inician con J. Nota. Los componentes Swing fueron nombrados por un estilo musical que fue popular all´ a en 1940. El nombre implica que los componentes tienen estilo y dinamismo. Las clases Swing son parte de un 1

Transcript of Introducci on a componentes...

Introduccion a componentes Swing

H. Tejeda

Mayo 2016

Indice

1. Introduccion 1

2. Clase JFrame 2

3. Clase JLabel 6

4. Manejador de diseno 9

5. Extension de la clase JFrame 11

6. Clases de entrada 13

7. Programacion de manejo de eventos 17

8. Receptores de eventos 21

9. Clases para seleccion 23

1. Introduccion

Las aplicaciones son mas amigables al usuario cuando estas contienen componentes interfaz deusuario o UI (User Interface). Los componentes UI son botones, campos de texto, y otros conlos cuales el usuario puede interactuar. Los creadores de Java han empacado una cantidad decomponentes preescritos en el paquete Swing. Los componentes Swing son elementos UI talescomo cuadros de dialogo y botones; se reconocen porque sus nombres inician con J.

Nota. Los componentes Swing fueron nombrados por un estilo musical que fue popular alla en 1940.

El nombre implica que los componentes tienen estilo y dinamismo. Las clases Swing son parte de un

1

conjunto mas general de capacidades de programacion UI que son llamadas las clases de fundacion

Java o JFC (Java Foundation Classes). JFC incluye las clases componentes Swing y algunas clases

del paquete java.awt.

Nota. En las primeras versiones de Java, los componentes tenıan nombres simples, tales como Frame

y Button. Los componentes no tenıan una apariencia consistente cuando se usaban con diferentes

navegadores y sistemas operativos. Cuando los programadores de Java disenaron clases nuevas y

mejoradas necesitaron nuevos nombres para las clases, ası que usaron una J precediendo cada nuevo

nombre de clase. Por lo tanto, los componentes Swing tienen nombres como JFrame, JButton,

JScrollbar, JOptionPane, etc.

Los componentes UI son tambien llamados controles o widgets (reproductores). Cada componenteSwing es un descendiente de un JComponent, el cual a su vez hereda desde la clase java.awt.Con-

tainer. Para usar los componentes UI Swing y sus metodos se debe insertar la sentencia import

javax.swing.* al inicio del programa, de esta forma se importa el paquete. La x en el nombre delpaquete representa la extension de las especificaciones del lenguaje Java original.

Nota. Casi todos los componentes Swing se dice que son componentes peso ligero porque estan

escritos completamente en Java y no descansan en el codigo del sistema operativo local. Esto significa

que los componentes no son “sobrecargados” teniendo que interactuar con el sistema operativo.

Algunos componentes Swing, como JFrame, se conocen como componentes peso pesado porque

requieren interactuar con el sistema operativo local. Un componente ligero reusa la ventana nativa

de su ancestro mas cercano peso pesado; un componente peso pesado tiene su propia ventana nativa

opaca. Los unicos componentes peso pesado usados en Swing son JFrame, JDialog, JWindow,

JApplet, awt.Component, awt.Container, y JComponent.

Cuando se usan componentes Swing estos son puestos, generalmente, en contenedores. Un con-tenedor es un tipo de componente que guarda otros componentes para que este grupo pueda sertratado como una sola entidad. Los contenedores estan definidos en la clase Container. Frecuen-temente, un contenedor toma la forma de una ventana que puede ser arrastrada, redimensionada,minimizada, restaurada, y cerrada.

La clase Component es una hija de la clase Object, y la clase Container es una hija de la claseComponent. Por lo tanto, cada objeto Container “es un” Component, y cada objeto Component

“es un” Object. La clase Window es una hija de Container. Los programadores de Java usan pocolos objetos Window porque la subclase Frame de Window y su subclase JFrame componente Swing,permiten crear objetos mas utiles. Los objetos Window no tienen barra de tıtulo, ni bordes.

2. Clase JFrame

Se crea un JFrame para poner otros objetos dentro para ser mostrados. Enseguida se muestra elarbol de herencia de la clase JFrame para mostrar la relacion con sus ancestros.

java.lang.Object

2

|

+--java.awt.Component

|

+---java.awt.Container

|

+---java.awt.Window

|

+---java.awt.Frame

|

+---javax.swing.JFrame

La clase JFrame tiene cuatro constructores:

JFrame() construye un nuevo marco que inicialmente es invisible y no tiene tıtulo.

JFrame(String tıtulo) crea un nuevo JFrame inicialmente invisible con el tıtulo indicado.

JFrame(GraphicsConfiguration gc) crea un JFrame en el GraphicsConfiguration de undispositivo de pantalla sin tıtulo.

JFrame(String tıtulo, GraphicsConfiguration gc) crea un JFrame con el tıtulo especi-ficado y el GraphicsConfiguration dado de una pantalla.

Se construye un JFrame como cualquier otro objeto, usando el nombre de la clase, un identificador, eloperador de asignacion, el operador new, y una llamada al constructor. Las siguientes dos sentenciasconstruyen dos JFrame: uno con el tıtulo “Hola” y otro sin tıtulo.

JFrame primerMarco = new JFrame("Hola");

JFrame segundoMarco = new JFrame();

Ya teniendo los objetos JFrame creados, se pueden usar algunos de los metodos utiles dados en elcuadro 1.

Suponiendo que se ha declarado un JFrame llamado primerMarco, se pueden usar las siguientessentencias para poner el tamano del objeto primerMarco a 250 pıxeles horizontalmente por 100verticalmente y pone el tıtulo del JFrame para mostrar un argumento String. Los pıxeles sonlos elementos de imagen, o pequenos puntos de luz, que hacen la imagen en el monitor de lacomputadora.

primerMarco.setSize(250, 100);

primerMarco.setTitle("Mi marco");

Cuando se pone el tamano de un JFrame, no se tiene el area completa disponible para usarla porqueparte del area es usada por la barra de tıtulo y los bordes del JFrame.

La aplicacion JFrame1, codigo 1, muestra una aplicacion que crea un JFrame pequeno y vacıo.

3

Metodo Descripcion

void setTitle(String) Pone el tıtulo del JFrame usando el argumentoString.

void setSize(int, int) Fija el tamano de un JFrame en pıxeles con el anchoy alto como argumento.

void setSize(Dimension) Fija el tamano de un JFrame usando un objetoDimension; el constructor Dimension(int, int)

crea un objeto que representa un ancho y una al-tura.

String getTitle() Regresa el tıtulo de un JFrame.void setResizable(boolean) Pone el JFrame para que sea redimensionable pa-

sando true al metodo, con false es no redimen-sionable.

boolean isResizable() Regresa true o false para indicar si el JFrame esredimensionable.

void setVisible(boolean) Hace un JFrame visible usando el argumento boo-leano true e invisible usando el argumento false.

void setBounds(int, int, int,

int)

Sobreescribe el comportamiento por defecto paraque el JFrame sea posicionado en la esquina su-perior izquierda en la pantalla del escritorio de lacomputadora; los primeros dos argumentos son lasposiciones horizontal y vertical de la esquina supe-rior izquierda del JFrame en el escritorio, y los dosargumentos finales fijan el ancho y la altura.

Cuadro 1: Metodos utiles heredados por la clase JFrame.

4

1 import javax . swing . ∗ ;2 public class JFrame1 {3 public stat ic void main ( St r ing [ ] a rgs ) {4 JFrame unMarco = new JFrame ( ”Primer Marco” ) ;5 unMarco . s e t S i z e (250 , 1 00 ) ;6 unMarco . s e t V i s i b l e ( true ) ;7 }8 }

Codigo 1: Aplicacion JFrame1.

La aplicacion JFrame1, codigo 1, crea un JFrame. Este se parece a marcos que se han visto cuandose usan programas UI diferentes. La razon para usar objetos marco similares es porque los usuariosya estan familiarizados con el ambiente de marcos. Cuando los usuarios ven marcos esperan ver unabarra de tıtulo en la cima con informacion de texto. Tambien esperan ver los botones de minimizar,maximizar o restaurar, y cerrar en alguna de la esquinas superiores del marco. Muchos usuariossuponen que pueden cambiar el tamano del marco arrastrando sus bordes o reposicionar la ventanaen la pantalla arrastrando la barra de titulo de la ventana a una nueva localidad.

En la aplicacion del codigo 1, las tres sentencias en el metodo main() son importantes. Despues deinstancia unMarco, se necesita hacer setVisible(true) para poder ver el JFrame, y tambien ponersu tamano ya que de otra forma solo la barra de tıtulo del JFrame es visible porque el tamano de estees 0 x 0 por defecto. Una razon por la cual el JFrame es invisible es porque este se podrıa construiren segundo plano mientras otras acciones estan ocurriendo y quizas se desearıa hacer visible mastarde. Algunos programadores usan el metodo show() en vez del metodo setVisible().

Cuando un usuario cierra un JFrame pulsando en el boton cerrar en alguna de la esquinas supe-riores, el comportamiento por defecto para el JFrame es ocultarse y para la aplicacion continuarejecutandose. Esto tiene sentido cuando hay otras tareas por completar para el programa despuesde que el marco principal fue cerrado—por ejemplo, mostrar marcos adicionales, cerrar archivosabiertos de datos, o imprimir un reporte de actividad. Cuando un JFrame sirve como una aplicacionde Swing se quiere que el programa termine cuando el usuario pulsa el boton cerrar. Para cambiar elcomportamiento se puede llamar al metodo setDefaultCloseOperation() de JFrame con algunode los siguientes cuatro valores como argumento:

JFrame.EXIT ON CLOSE termina el programa cuando el JFrame es cerrado.

WindowConstants.DISPOSE ON CLOSE cierra el marco, dispone el objeto JFrame, y mantieneen ejecucion la aplicacion.

WindowConstants.DO NOTHING ON CLOSE mantiene el JFrame abierto y continua ejecutando-se. En otras palabras, deshabilita el boton cerrar.

WindowConstants.HIDE ON CLOSE cierra el JFrame y continua ejecutandose; este es el com-portamiento por defecto.

Cuando se ejecuta una aplicacion en cual se ha olvidado salir cuando el JFrame es cerrado, se puedeterminar el programa tecleando CTRL+C.

5

Personalizacion de la apariencia de un JFrame

La apariencia de un JFrame es dada por el sistema operativo en el cual el programa este eje-cutandose. El diseno de los elementos que controlan el marco se parecen y se comportan como lohace cualquier otra aplicacion grafica. Los botones y el ıcono, en el caso de que se muestre, sonconocidos como decoraciones ventana; por defecto las decoraciones ventana son proporcionadaspor el sistema operativo. Se puede pedir que el mirar y sentir de Java de las decoraciones para unmarco. Un mirar y sentir es la apariencia y comportamiento por defecto de cualquier interfaz deusuario.

Opcionalmente, se puede poner el mirar y sentir de un JFrame usando el metodo setDefaultLook-

AndFeelDecorated(). La aplicacion JFrame2, codigo 2, hace una llamada a este metodo en la lınea4.

1 import javax . swing . ∗ ;2 public class JFrame2 {3 public stat ic void main ( St r ing [ ] a rgs ) {4 JFrame . setDefaultLookAndFeelDecorated ( true ) ;5 JFrame unMarco = new JFrame ( ”Segundo Marco” ) ;6 unMarco . s e t S i z e (250 , 1 00 ) ;7 unMarco . s e t V i s i b l e ( true ) ;8 }9 }

Codigo 2: La clase JFrame2.

Puede ser que al usar el metodo setDefaultLookAndFeelDecorated() el sistema operativo impidamodificar su apariencia, como en Mac OS X.

Actividad 1. Escribir una aplicacion grafica que muestre en el tıtulo de la ventana su nombre ytenga un tamano cuadrado. Ademas la aplicacion debe terminar cuando se cierre el marco.

3. Clase JLabel

Uno de los componentes que se podrıa poner en un JFrame es un JLabel. JLabel es una clase Swingincorporada que tiene texto que se quiere mostrar. La jerarquıa de herencia de la clase JLabel semuestra enseguida:

java.lang.Object

|

+--java.awt.Component

|

+---java.awt.Container

|

+---javax.swing.JComponent

|

+---javax.swing.JLabel

6

Los constructores para la clase JLabel incluyen los siguientes:

JLabel() crea una instancia JLabel sin imagen con una cadena vacıa para el tıtulo.

JLabel(Icon imagen) crea una instancia JLabel con la imagen especificada.

JLabel(Icon imagen, int alineacionHorizontal) crea una instancia JLabel con la ima-gen especificada y la alineacion horizontal.

JLabel(String texto) crea una instancia JLabel con el texto especificado.

JLabel(String texto, Icon imagen, int alineacionHorizontal) crea una instancia J-

Label con el texto, la imagen, y la alineacion horizontal especificados.

JLabel(String texto, int alineacionHorizontal) crea una instancia JLabel con el tex-to y la alineacion horizontal indicados.

Se puede crear un JLabel llamado saludo que tenga las palabras “Buen dıa” con la siguientesentencia:

JLabel saludo = new JLabel("Buen dıa");

Para agregar el objeto saludo al objeto JFrame llamado unMarco usando el metodo add() comosigue:

unMarco.add(saludo);

La aplicacion JFrame3, codigo 3, muestra la creacion de JFrame al que enseguida se le pone sutamano y la operacion de cierre. Luego un JLabel es creado y agregado al JFrame.

1 import javax . swing . ∗ ;2 public class JFrame3 {3 public stat ic void main ( St r ing [ ] a rgs ) {4 f ina l int ANCHOMARCO = 250 ;5 f ina l int ALTO MARCO = 100 ;6 JFrame unMarco = new JFrame ( ” Tercer Marco” ) ;7 unMarco . s e t S i z e (ANCHO MARCO, ALTO MARCO) ;8 unMarco . s e tDe fau l tC lo seOperat i on ( JFrame .EXIT ON CLOSE ) ;9 JLabel sa ludo = new JLabel ( ”Buen dıa” ) ;

10 unMarco . add ( sa ludo ) ;11 unMarco . s e t V i s i b l e ( true ) ;12 }13 }

Codigo 3: La clase JFrame3.

La contraparte del metodo add() es el metodo remove(). La siguiente sentencia quita saludo deunMarco:

7

unMarco.remove(saludo);

Si se agrega, o quita un componente de un contenedor despues de que este se hizo visible, se deberıatambien llamar los metodos invalidate(), validate() y repaint() para ver los resultados delas acciones. Cada uno realiza funciones ligeramente diferentes pero las tres juntas garantizan queel resultado de cambios en el diseno tomaran efecto. Los metodos invalidate() y validate() sonparte de la clase Container, y repaint() es parte de la clase Component.

Nota. Si se agrega o quita un componente en un objeto JFrame durante la construccion, no se

tiene que llamar al metodo repaint() si despues se modifica el componente, como por ejemplo,

cambiando el texto. Solo se necesita llamar a repaint() si se agrega o quita un componente despues

de la construccion.

Se puede cambiar el texto en un JLabel usando el metodo setText() de la clase Component conel objeto JLabel y pasandole un String. El siguiente codigo cambia el valor mostrado en el JLabelsaludo:

saludo.setText("Suerte");

Se puede recuperar el texto en un JLabel, o cualquier otro Component, usando el metodo getText(),el cual regresa el String guardado actualmente.

Cambiar la fuente de un JLabel

Java proporciona una clase Font para crear un objeto que guarde el tipo de fuente, y la informaciondel estilo y del tamano de la fuente. El metodo setFont() requiere un argumento objeto Font.Para construir un objeto Font, se necesitan tres argumentos: tipo de fuente, estilo, y tamano enpuntos.

El argumento tipo de fuente para el constructor Font es un String representando unafuente. Las fuentes comunes tienen nombres como Arial, Century, Monospaced, y Times NewRoman. El argumento tipo de fuente es solo una peticion; el sistema operativo en el cual elprograma se ejecuta podrıa no tener acceso, y si es necesario, este lo sustituye con una fuentepor defecto.

El argumento estilo aplica un atributo al texto mostrado y es uno de tres valores: Font.PLAIN,Font.BOLD, o Font.ITALIC.

El argumento tamano en puntos es un entero que representa aproximadamente 1/72 deuna pulgada. El texto impreso es generalmente de 12 puntos; una cabecera podrıa ser de 30puntos.

Nota. En impresion, el tamano de punto define una medida entre lıneas de texto en un docu-

mento de texto con interlineado simple. Java adopta la convencion de que un punto en una

pantalla es equivalente a una unidad en las coordenadas del usuario.

8

Para dar a un objeto JLabel una nueva fuente, se puede crear un objeto Font, como en el siguiente:

Font fuenteCabecera = new Font("Monospaced", Font.BOLD, 36);

Luego se usa el metodo setFont() para asignar el objeto Font al objeto JLabel con una sentenciacomo la siguiente:

saludo.setFont(fuenteCabecera);

La aplicacion JFrame4, codigo 4, muestra en las lıneas 2, 3, 7, 8, y 12 los cambios que se hicierona JFrame3 para usar otro tipo de fuente con diferente tamano y apariencia.

1 import javax . swing . ∗ ;2 import java . awt . ∗ ;3 public class JFrame4 {4 public stat ic void main ( St r ing [ ] a rgs ) {5 f ina l int ANCHOMARCO = 250 ;6 f ina l int ALTO MARCO = 100 ;7 Font fuente = new Font ( ” Ar ia l ” , Font .BOLD, 3 6 ) ;8 JFrame unMarco = new JFrame ( ”Cuarta Ventana” ) ;9 unMarco . s e t S i z e (ANCHO MARCO, ALTO MARCO) ;

10 unMarco . s e tDe fau l tC lo seOperat i on ( JFrame .EXIT ON CLOSE ) ;11 JLabel sa ludo = new JLabel ( ”Buen dıa” ) ;12 sa ludo . setFont ( fuente ) ;13 unMarco . add ( sa ludo ) ;14 unMarco . s e t V i s i b l e ( true ) ;15 }16 }

Codigo 4: La clase JFrame4.

No es obligatorio proporcionar un identificador para un objeto Font. Se pudo omitir la lınea 7 en elcodigo 4 y poner la fuente en saludo con la siguiente sentencia, la cual usa un objeto Font anonimo:

saludo.setFont(new Font("Arial", Font.BOLD, 36));

Despues de crear un objeto Font, se puede crear un nuevo objeto con un tipo y tamano diferenteusando el metodo deriveFont() con los argumentos apropiados. Por ejemplo, las siguientes dossentencias crean el objeto fuenteCabecera y el fuenteCuerpoTexto que esta basado en el primerobjeto:

Font fuenteCabecera = new Font("Arial", Font.BOLD, 36);

Font fuenteCuerpoTexto = fuenteCabecera.deriveFont(Font.PLAIN, 14);

4. Manejador de diseno

Cuando se quiere agregar multiples componentes a un JFrame u otro contenedor, usualmente se re-quiere proporcionar instrucciones para la colocacion de los componentes. En la aplicacion JFrame5,

9

codigo 5, dos JLabel son creados y agregados a un JFrame en las sentencias de las lıneas 11—12.

1 import javax . swing . ∗ ;2 public class JFrame5 {3 public stat ic void main ( St r ing [ ] a rgs ) {4 f ina l int ANCHOMARCO = 250 ;5 f ina l int ALTO MARCO = 100 ;6 JFrame unMarco = new JFrame ( ”Quinta Ventana” ) ;7 unMarco . s e t S i z e (ANCHO MARCO, ALTO MARCO) ;8 unMarco . s e tDe fau l tC lo seOperat i on ( JFrame .EXIT ON CLOSE ) ;9 JLabel sa ludo = new JLabel ( ”Hola” ) ;

10 JLabel sa ludo2 = new JLabel ( ”¿Quien e r e s ?” ) ;11 unMarco . add ( sa ludo ) ;12 unMarco . add ( sa ludo2 ) ;13 unMarco . s e t V i s i b l e ( true ) ;14 }15 }

Codigo 5: La clase JFrame5.

Cuando se ejecuta la aplicacion JFrame5 solo la ultima JLabel que fue agregada es visible, a pesarde que se agregaron dos etiquetas al marco. La segunda JLabel fue puesta encima de la primera,tapandola completamente. Si se continuan agregando mas JLabel en el programa, solo la ultimaagregada al JFrame sera visible.

Para colocar multiples componentes en posiciones especificadas en un contenedor de tal forma queno se oculten entre ellas, se debe usar explıcitamente un manejador de diseno, una clase quecontrola el posicionamiento de componentes. El comportamiento por defecto de un JFrame es dadopor un manejador llamado BorderLayout. Un manejador BorderLayout divide un contenedor enregiones. Cuando no se indica una region en la cual un componente se coloca, este se coloca siempreen el centro, y si estaba otro componente, lo tapa.

Al agregar componentes usando el manejador FlowLayout, estos son colocados en un renglon, ycuando el renglon se llena, los componentes automaticamente se ponen en el siguiente renglon.

Tres constantes estan definidas en la clase FlowLayout para indicar como los componentes sonposicionados en cada renglon de su contenedor. Estas son FlowLayout.LEFT, FlowLayout.RIGHT,y FlowLayout.CENTER. Para crear un manejador de diseno llamado flujo que posicione los com-ponentes a la derecha, se usa la siguiente sentencia:

FlowLayout flujo = new FlowLayout(FlowLayout.RIGHT);

En caso de no indicar como los componentes son distribuidos, por defecto estos son centrados encada renglon.

Una vez que el manejador de diseno ha sido creado entonces puede ser puesto al objeto JFrame

haciendo lo siguiente:

unMarco.setLayout(flujo);

Se puede compactar el codigo usando un objeto FlowLayout anonimo con:

10

unMarco.setLayout(new FlowLayout(FlowLayout.RIGHT));

La aplicacion JFrame6, codigo 6, ha puesto el manejador de diseno del JFrame para que componentesmultiples sean visibles.

1 import javax . swing . ∗ ;2 import java . awt . ∗ ;3 public class JFrame6 {4 public stat ic void main ( St r ing [ ] a rgs ) {5 f ina l int ANCHOMARCO = 250 ;6 f ina l int ALTO MARCO = 100 ;7 JFrame unMarco = new JFrame ( ” Sexta Ventana” ) ;8 unMarco . s e t S i z e (ANCHO MARCO, ALTO MARCO) ;9 unMarco . s e tDe fau l tC lo seOperat i on ( JFrame .EXIT ON CLOSE ) ;

10 JLabel sa ludo = new JLabel ( ”Hola” ) ;11 JLabel sa ludo2 = new JLabel ( ”¿Quien e r e s ?” ) ;12 unMarco . setLayout (new FlowLayout ( FlowLayout .RIGHT) ) ;13 unMarco . add ( sa ludo ) ;14 unMarco . add ( sa ludo2 ) ;15 unMarco . s e t V i s i b l e ( true ) ;16 }17 }

Codigo 6: La clase JFrame6.

Al ejecutar la aplicacion JFrame6 se deben ver los dos JLabel, uno al lado del otro porque se usaun FlowLayout. Si hubiera mas JLabel u otros componentes, estos serıan colocados continuamentelado por lado a traves del JFrame hasta que no haya mas espacio.

5. Extension de la clase JFrame

Se puede instanciar un objeto JFrame simple dentro del metodo main() de una aplicacion o encualquier otro metodo de cualquier clase que sea escrita. Alternativamente, se puede crear supropia clase que descienda de la clase JFrame. La ventaja de crear una clase hija desde JFrame esla posibilidad de poder poner las propiedades del JFrame dentro del constructor de objetos; luego,cuando se crea su objeto hijo JFrame, este es dotado automaticamente con las caracterısticas quese hayan especificado, tales como el tamano, el tıtulo, y la operacion de cierre por defecto.

Para crear una clase hija se usa la palabra reservada extends en la cabecera de la clase, seguido porel nombre de la clase padre. Para llamar el constructor de la clase padre se usa la palabra reservadasuper(), y debera ser la primera sentencia en el constructor de la clase hija.

La clase JMiMarco, codigo 7, extiende a JFrame. En el constructor de JMiMarco, el constructorsuper() JFrame es llamado; este acepta un argumento String para usarlo como el tıtulo del JFrame.El constructor de JMiMarco tambien fija el tamano, la operacion de cierre por defecto y la visibilidadpara cada JMiMarco. Cada uno de los metodos—setSize(), setDefaultCloseOperation(), ysetVisible—aparecen en el constructor sin un objeto, porque el objeto es el JMiMarco actualsiendo construido.

11

1 import javax . swing . ∗ ;2 public class JMiMarco extends JFrame {3 f ina l int ANCHO = 200 ;4 f ina l int ALTO = 120 ;5 public JMiMarco ( ) {6 super ( ”Mi marco” ) ;7 s e t S i z e (ANCHO, ALTO) ;8 s e tDe fau l tC lo seOperat ion ( JFrame .EXIT ON CLOSE ) ;9 s e t V i s i b l e ( true ) ;

10 }11 }

Codigo 7: La clase JMiMarco.

Cuando se ejecuta la aplicacion CrearDosObjetosMiMarco, codigo 8, los dos objetos JMiMarco sonmostrados con el segundo encima del primero. Para ver el primer marco se debe arrastrar el segundomarco.

1 public class CrearDosObjetosMiMarco {2 public stat ic void main ( St r ing [ ] a rgs ) {3 JMiMarco miMarco = new JMiMarco ( ) ;4 JMiMarco miSegundoMarco = new JMiMarco ( ) ;5 }6 }

Codigo 8: La aplicacion CrearDosObjetosMiMarco.

Nota. Se podrıa usar el metodo setBounds() con uno de los objetos JMiMarco para no tener

que arrastrar uno de los objetos JMiMarco para ver el otro. La clase Objeto incluye el metodo

setLocation() que se puede usar con un JFrame. Para usar este metodo, se deben dar valores para

las posiciones horizontal y vertical como argumentos del metodo.

Nota. Se termina la aplicacion cuando se pulsa en el boton cerrar de alguno de los dos objetos

JMiMarco. Cada objeto tiene la misma operacion de cierre por defecto porque cada uno usa el mismo

constructor que indica esa operacion. Para permitir que solo un JMiMarco controle la terminacion

del programa, se podrıa usar el metodo setDefaultCloseOperation() con alguno de los objetos

en la aplicacion para cambiar su comportamiento de cierre, quizas usando DISPOSE ON CLOSE para

descartar uno de los marcos pero manteniendo la aplicacion en ejecucion.

Cuando se extiende un JFrame para crear una clase nueva personalizada, se debe recordar tomardecisiones con los atributos que se quieren fijar dentro de la clase y los que se quieren dejar a lasaplicaciones que usaran la clase. Por ejemplo, se puede poner la sentencia setVisible() dentro delconstructor de la clase hija JFrame, o se puede permitir a la aplicacion usar el metodo setVisible()

precedido por el nombre de un objeto instanciado seguido de un punto. Cualquiera trabaja, perosi no se hace ninguna, el marco no sera visible.

Nota. Algunos programadores ponen un metodo main() dentro de una clase como JMiMarco. Luego

la clase da la opcion para ser usada para instanciar objetos, como en la aplicacion CrearDosObjetosMiMarco,

o para ser usada ejecutandose como un programa que crea un objeto.

12

6. Clases de entrada

Un JFrame tambien contiene otras caracterısticas de ventana, tales como JTextField, JButton, einformacion sobre herramientas (tool tips).

Clase JTextField

Un JTextField es un componente en el cual un usuario puede teclear una lınea de texto. El textocomprende cualquier caracter que se pueda meter del teclado o aplicacion, incluyendo numeros ysignos de puntuacion. La siguiente figura muestra la jerarquıa de herencia de la clase JTextField.

java.lang.Object

|

+--java.awt.Component

|

+---java.awt.Container

|

+---javax.swing.JComponent

|

+---javax.swing.text.JTextComponent

|

+---javax.swing.JTextField

En un JTextField un usuario teclea una lınea de texto y luego presiona la tecla Intro o pulsa unboton con el raton para meter los datos. Se puede construir un objeto JTextField usando uno delos varios constructores:

JTextField() construye un nuevo JTextField.

JTextField(int columnas) construye un nuevo JTextField vacıo con la cantidad indicadade columnas.

JTextField(String texto) construye un nuevo JTextField inicializado con el texto espe-cificado.

JTextField(String texto, int columnas) construye un nuevo JTextField inicializadocon el texto dado y la cantidad de columnas indicada.

Por ejemplo, para tener un JTextField que tenga suficiente espacio para que un usuario puedemeter 10 caracteres, se puede codificar lo siguiente:

JTextField respuesta = new JTextField(10);

Para agregar el JTextField llamado respuesta a un JFrame llamado marco, se indica con:

13

marco.add(respuesta);

La cantidad de caracteres que un JTextField puede mostrar depende de la fuente usada y loscaracteres tecleados. En la mayorıa de las fuentes, m es mas ancha que i, ası un JTextField detamano 10 usando la fuente Arial puede mostrar 24 caracteres i, pero solo 8 caracteres m.

Se debe intentar anticipar cuanto caracteres los usuarios podrıan ingresar cuando se crea unJTextField. El usuario puede meter mas caracteres que aquellos que son mostrados, pero loscaracteres extra se desplazan fuera de la vista. Puede ser desconcertante intentar meter datos enun campo que no es lo suficientemente grande, ası que es mejor sobreestimar que subestimar eltamano de un campo de texto.

Otros metodos estan disponibles para ser usados con objetos JTextField. El metodo setText()

permite cambiar el texto en un JTextField, u otro Componet, que ha sido creado, como se muestraenseguida:

respuesta.setText("Gracias");

Despues de que el usuario ingreso texto en un JTextField, se puede limpiar con una sentenciacomo la siguiente, la cual asigna una cadena vacıa al texto:

respuesta.setText("");

El metodo getText() permite recuperar el String de texto en un JTextField, u otro Component,como en:

String entradaUsuario = respuesta.getText();

Cuando un JTextField tiene la capacidad de aceptar pulsaciones de teclas, el JTextField eseditable. Un JTextField por defecto es editable. Si no se quierer que el usuario pueda ingresardatos en un JTextField, se puede mandar un valor booleano al metodo setEditable() paracambiar el estado editable de un JTextField. Por ejemplo, si se quiere dar al usuario una cantidadlimitada de oportunidades de contestar una pregunta correctamente, se pueden contar los intentosde entrada de datos y entonces prevenir al usuario de reemplazar o editar los caracteres en elJTextField usando una sentencia como:

if (intentos > LIMITE)

respuesta.setEditable(false );

Clase JButton

Un JButton es un Component en el cual el usuario puede pulsar con el raton para hacer unaseleccion. Hay cinco constructores JButton y son:

14

JButton() crea un boton sin texto.

JButton(Icon ıcono) crea un boton con un ıcono de tipo Icon o ImageIcon.

JButton(String texto) crea un boton con texto.

JButton(String texto, Icon icon) crea un boton con el texto inicial y un ıcono del tipoIcon o ImageIcon.

JButton(Action a) crea un boton en el cual sus propiedades son tomadas de la Action

proporcionada.

La jerarquıa de herencia de la clase JButton es la siguiente:

java.lang.Object

|

+--java.awt.Component

|

+---java.awt.Container

|

+---javax.swing.JComponent

|

+---javax.swing.AbstractButton

|

+---javax.swing.JButton

Para crear un JButton con la etiqueta “Pulsar cuando este listo”, se puede escribir lo siguiente:

JButton botonListo = new JButton("Pulsar cuando este listo");

Se puede agregar un JButton a un JFrame usando el metodo add(). Se puede cambiar la etiquetade un JButton con el metodo setText(), como en:

botonListo.setText("¡No me presiones nuevamente!");

Se puede recuperar el texto de un JButton y asignarlo a un objeto String con el metodo getText(),usando:

String queEstaEnJButton = botonListo.getText();

La clase JFrameConMuchosComponentes, codigo 9, extiende JFrame y guarda varios componentes.Como los componentes, dos JLabel, un JTextField y un JButton son agregados al marco, estosson puestos de izquierda a derecha en renglones horizontales en la superficie del JFrame.

15

1 import javax . swing . ∗ ;2 import java . awt . ∗ ;3 public class JFrameConMuchosComponentes extends JFrame {4 f ina l int ANCHO = 350 ;5 f ina l int ALTO = 150 ;6 public JFrameConMuchosComponentes ( ) {7 super ( ” Mostrar muchos componentes” ) ;8 s e t S i z e (ANCHO, ALTO) ;9 s e tDe fau l tC lo seOperat ion ( JFrame .EXIT ON CLOSE ) ;

10 JLabel cabecera = new JLabel ( ” Este marco t i e n e v a r i o s componentes” ) ;11 cabecera . setFont (new Font ( ” Ar ia l ” , Font .BOLD, 1 6 ) ) ;12 JLabel mensajeNombre = new JLabel ( ” I n g r e s a r su nombre : ” ) ;13 JTextFie ld campoNombre = new JTextFie ld ( 1 2 ) ;14 JButton boton = new JButton ( ” Pulsar para cont inuar ” ) ;15 setLayout (new FlowLayout ( ) ) ;16 add ( cabecera ) ;17 add ( mensajeNombre ) ;18 add (campoNombre ) ;19 add ( boton ) ;20 }21 }

Codigo 9: La clase JFrameConMuchosComponentes.

La aplicacion DemoComponentes, codigo 10, instancia un objeto del tipo JFrameConMuchosComponentes.

1 public class DemoComponentes {2 public stat ic void main ( St r ing [ ] a rgs ) {3 JFrameConMuchosComponentes marco =4 new JFrameConMuchosComponentes ( ) ;5 marco . s e t V i s i b l e ( true ) ;6 }7 }

Codigo 10: Aplicacion DemoComponentes.

Al ejecutar la aplicacion DemoComponentes, el JFrame contiene todos los componentes que fueronagregados en el constructor del marco. El usuario puede minimizar o restaurar el marca y puedemodificar su tamano arrastrando los bordes del marco. El usuario puede teclea en el JTextFieldy pulsar el JButton. Cuando el boton es pulsado, este parece que fue presionado al igual que otrosbotones usados en diferentes aplicaciones. Sin embargo, cuando el usuario teclea o pulsa el boton,no ocurren acciones resultantes porque no se ha sido escrito todavıa codigo para manejar es eventosiniciados por usuario.

Uso de informacion sobre herramientas

Informacion sobre herramientas (tool tips) son ventanas emergentes que pueden ayudar alusuario a entender el proposito de los componentes en una aplicacion; la informacion aparece cuandoun usuario flota el apuntador del raton encima del componente. Se define el texto que sera mostradoen una sugerencia usando el metodo setToolTipText() y pasandole un String apropiado. Enla clase JFrameConMuchosComponentes, codigo 9, se puede agregar una sugerencia al componente

16

boton usando la siguiente sentencia en el constructor JFrame:

boton.setToolTipText("Pulsa este boton");

Actividad 2. Crear una aplicacion Swing que muestre un JFrame que tenga un JLabel, unJTextField, y un JButton. El diseno de esta aplicacion debera incluir una clase que extiendaa la clase JFrame, la cual tendra los componentes como campos de esta clase con la correspondien-te asignacion de los objetos instanciados; en el constructor de la clase hija configurar el marco yagregar los componentes. Luego escribir una aplicacion que cree un objeto de la clase hija donde sedebera fijar el tamano de la ventana en 350 de ancho y 100 de alto usando constantes.

7. Programacion de manejo de eventos

Un evento ocurre cuando un usuario realiza una accion en un componente, tal como pulsar elraton en un objeto JButton. En un programa de manejo de eventos, el usuario podrıa iniciarcualquier cantidad de eventos en cualquier orden. Si se usa un programa procesador de textos, setienen docenas de opciones disponibles en cualquier momento. Se puede teclear texto, seleccionarel texto con el raton, pulsar un boton para cambiar el texto a negritas, o a italicas, escoger unelemento del menu, etc. Con cada documento creado se escogen opciones en el orden que parecemas apropiado en el momento. El programa procesador de textos debera estar listo para respondercualquier evento que haya sido iniciado.

Dentro de un programa de manejo de eventos, un componente en el cual un evento es generado esla fuente del evento. Un boton que un usuario puede pulsar es un caso de una fuente; un campode texto donde un usuario puede ingresar texto es otra fuente. Un objeto que esta interesado en unevento es un receptor (listener). No todos los objetos oyen por todos los posibles eventos—comoen algunos programas en los cuales se pulsa en diferentes areas de la pantalla y no sucede nada. Sise quiere que un objeto sea un receptor para un evento, se debe registrar el objeto como un receptorde la fuente.

Un objeto fuente componente Java, como un boton, mantiene una lista de receptores registradosy notifica a todos ellos cuando cualquier evento ocurre. Un JFrame podrıa querer ser notificadode cualquier pulsacion en su superficie. Cuando un receptor “recibe las noticias”, un metodo demanejo de evento contenido en el objeto receptor responde al evento.

Nota. Un objeto fuente y un objeto receptor puede ser el mismo objeto. Por ejemplo, se podrıa

programar un JButton para cambiar su propia etiqueta cuando un usuario lo pulse.

Para responder a eventos del usuario dentro de alguna clase creada, se debe hacer lo siguiente:

Preparar la clase para aceptar mensajes de eventos.

Indicar a la clase para que espere eventos que pasaran.

Indicar a la clase como responder a los eventos.

17

Preparar la clase para aceptar mensajes de eventos

Se prepara la clase para aceptar eventos de pulsacion del boton importando el paquete java.awt.-

event en el programa y agregando la frase implements ActionListener a la cabecera de la clase.En el paquete java.awt.event se incluyen clases evento como ActionEvent, ComponentEvent, yTextEvent. ActionListener es una interfaz—un tipo de clase con un conjunto de especificacionespara metodos que se pueden usar. Implementar ActionListener da especificaciones estandar demetodos de eventos que permiten al receptor trabajar con ActionEvent, el cual es el tipo de eventoque ocurre cuando se pulsa un boton.

Indicar a la clase para que espere eventos que pasaran

Se le dice a una clase que espere eventos ActionEvent con el metodo addActionListener().Si se ha declarado un JButton llamado unBoton, y se quiere realizar una accion cuando el usua-rio pulse unBoton, unBoton es la fuente de un mensaje, y se puede considerar a la clase comoun destino al cual se manda este. La referencia this significa “este objeto actual”, ası el codi-go unBoton.addActionListener(this); hace que cualquier mensaje ActionEvent (pulsar boton)que venga de unBoton sea enviado a “este objeto actual”.

Nota. No todos los eventos son ActionEvent con un metodo addActionListener(). Por ejemplo,

KeyListener tiene un metodo addKeyListener, y FocusListener tiene un metodo addFocusListener.

Indicar a la clase como responder a los eventos

La interfaz ActionListener contiene la especificacion del metodo actionPerformed(ActionEvent

e). Cuando una clase, tal como un JFrame, fue registrada como un receptor para un Component,tal como un JButton, y un usuario pulsa el JButton, el metodo actionPerformed() se ejecuta.Se implementa el metodo actionPerformed() usando la siguiente cabecera, donde e representacualquier nombre que se quiera para el evento que inicio la notificacion al ActionListener, el cuales el JFrame:

public void actionPerformed(ActionEvent e)

El cuerpo del metodo contiene cualquier sentencia que se quiera ejecutar cuando la accion ocurre. Sepodrıa querer realizar un calculo matematico, construir nuevos objetos, generar salida, o ejecutarcualquier otra operacion. En la clase JVentanaHola, codigo 11, un JFrame contiene un JLabel

que pide al usuario un nombre, un JTextField en el cual el usuario puede teclear una respuesta,un JButton para pulsar, y una segunda JLabel que muestra el nombre ingresado por el usuario.El metodo actionPerformed() se ejecuta cuando el usuario pulsa el boton JButton; dentro delmetodo, la cadena que un usuario ha tecleado en el JTextField es recuperada y guardada en lavariable nombre. El nombre es luego usado como de un String que altera la segunda JLabel delJFrame.

18

1 import javax . swing . ∗ ;2 import java . awt . ∗ ;3 import java . awt . event . ∗ ;4 public class JVentanaHola extends JFrame5 implements Act ionL i s t ene r {6 JLabel pregunta = new JLabel ( ”¿Cua l e s su nombre?” ) ;7 Font fuenteGrande = new Font ( ” Ar ia l ” , Font .BOLD, 1 6 ) ;8 JTextFie ld r e spue s ta = new JTextFie ld ( 1 0 ) ;9 JButton unBoton = new JButton ( ” Pulsa aquı” ) ;

10 JLabel sa ludo = new JLabel ( ”” ) ;11 f ina l int ANCHO = 275 ;12 f ina l int ALTURA = 225 ;13 public JVentanaHola ( ) {14 super ( ”Ventana Hola” ) ;15 s e t S i z e (ANCHO, ALTURA) ;16 pregunta . setFont ( fuenteGrande ) ;17 sa ludo . setFont ( fuenteGrande ) ;18 setLayout (new FlowLayout ( ) ) ;19 add ( pregunta ) ;20 add ( r e spue s ta ) ;21 add ( unBoton ) ;22 add ( sa ludo ) ;23 s e tDe fau l tC lo seOperat ion ( JFrame .EXIT ON CLOSE ) ;24 unBoton . addAct ionLis tener ( this ) ;25 }26 public void act ionPerformed ( ActionEvent e ) {27 St r ing nombre = re spue s ta . getText ( ) ;28 St r ing mensaje = ”Hola ” + nombre ;29 sa ludo . setText ( mensaje ) ;30 }31 }

Codigo 11: La clase JVentanaHola.

La aplicacion JDemoHola, codigo 12, instancia un objeto JVentanaHola y lo hace visible.

1 public class JDemoHola {2 public stat ic void main ( St r ing [ ] a rgs ) {3 JVentanaHola ventana = new JVentanaHola ( ) ;4 ventana . s e t V i s i b l e ( true ) ;5 }6 }

Codigo 12: Aplicacion JDemoHola.

Cuando se ejecuta la aplicacion JDemoHola, la cual instancia un objeto JVentanaHola, despues deque el usuario ingresa un nombre, el programa lo saluda con el nombre despues de que el usuariopulsa el boton.

Cuando mas de un componente es agregado y registrado a un JFrame, podrıa ser necesario de-terminar cual componente fue usado para iniciar un evento. En la clase JVentanaHola, codigojventanahola, se podrıa querer que el usuario pueda ver el mensaje despues de pulsar el boton ode presionar la tecla Intro en el JTextField. En ese caso, se podrıa designar a ambos como fuentes

19

de mensaje usando el metodo addActionListener() con cada uno, como sigue:

unBoton.addActionListener(this);

respuesta.addActionListener(this);

Estas dos sentencias hacen que el JFrame (this) el receptor de cualquier objeto. El JFrame tiene unsolo metodo actionPerformed(), ası que este es el metodo que se ejecuta cuando el boton unBoton

mande un mensaje o el campo de texto respuesta.

Si se quiere que acciones diferentes ocurran dependiendo del generador del evento, se debe de-terminar la fuente del evento. Dentro del metodo actionPerformed(), se puede usar el metodogetSource() del objeto enviado para determinar cual componente genero el evento. Por ejemplo,dentro de un metodo con la cabecera public void actionPerformed(ActionEvent e), e es unActionEvent. ActionEvent y otras clases evento son parte del paquete java.awt.event y sonsubclases de la clase EventObject. Para determinar cual objeto genero el ActionEvent, se usa lasiguiente sentencia:

Object fuente = e.getSource();

Por ejemplo, si un JFrame contiene dos JButton llamados opcion1 y opcion2, se puede usar laestructura de decision en el siguiente metodo para tomar diferentes acciones dependiendo del botonpulsado. Si una fuente de evento es un JButton, JTextField, u otro Component, este puede serasignado a un Object porque todos los componentes descienden de Object.

public void actionPerformed(ActionEvent e) {Object fuente = e.getSource();

if (fuente == opcion1)

// ejecutar estas sentencias cuando el usuario pulse opcion1

else

// ejecutar estas sentencias cuando el usuario pulse opcion2

}

Alternativamente, se puede tambien usar la palabra reservada instanceof para determinar lafuente del evento. instanceof es usada cuando es necesario conocer solo el tipo del componente,en vez del componente que disparo el evento. Por ejemplo, si se quiere tomar alguna accion cuandoun usuario ingresa datos en cualquier JTextField, pero no cuando un evento es generado por untipo diferente de Component, se usa el formato de metodo mostrado enseguida:

void actionPerformed(ActionEvent e) {Object fuente = e.getSource();

if (fuente instanceof JTextField) {// ejecutar las sentencias cuando cualquier

// JTextField genera el evento, pero no cuando

// un JButton u otro Component lo hace.

}}

20

Metodo setEnabled()

Cuando se usan aplicaciones hay ocasiones en las cuales un componente se deshabilita o deja de serusable. Por ejemplo, un JButton podrıa oscurecerse y deja de responder cuando el programadorno quiera que se tenga acceso a este. Los componentes estan habilitados por defecto, pero se puedeusar el metodo setEnabled() para hacer un componente disponible o no pasando true o false aeste, respectivamente.

Actividad 3. Agregar funcionalidad al JButton y al JTextField de la actividad 6. Al pulsar elboton o presionar la tecla Intro se debera cambiar el texto de la etiqueta para que muestre unmensaje de agradecimiento y para que el boton muestre la cadena “Hecho”.

Actividad 4. Repetir la actividad anterior pero ahora solo se modificara el texto de la etiquetapara que indique quien fue la fuente del evento, si el boton o el campo de texto.

8. Receptores de eventos

Varios tipos de receptores existen en Java, y cada uno de estos puede manejar un tipo de eventoespecıfico. Una clase puede implementar tantos receptores como ocupe—por ejemplo, una clasepodrıa requerir responder a la pulsacion de un boton del raton y a un teclazo, ası que se deberanimplementar las interfaces ActionListener y KeyListener. El cuadro 2 lista algunos receptoresde eventos y los tipos de eventos para los cuales son usados.

Receptor Tipos de eventos Ejemplo

ActionListener Eventos de accion Pulsar botonAdjustmentListener Eventos de ajuste Mover barra de desplaza-

mientoChangeListener Eventos de cambio Reposicionar deslizadorFocusListener Eventos del foco del teclado Gana o pierde el foco un

campo de textoItemListener Eventos de elementos Cambiar estado de casilla

de verificacionKeyListener Eventos del teclado Ingresar textoMouseListener Eventos del raton Pulsar boton del ratonMouseMotionListener Eventos de movimiento del

ratonMover raton

WindowListener Eventos de la ventana Cerrar ventana

Cuadro 2: Lista de algunos receptores de eventos

Un evento ocurre cada vez que un usuario teclea o pulsa un boton del raton. Cualquier objeto puedeser notificado de un evento siempre y cuando este implemente la interfaz apropiada y sea registradocomo un receptor de eventos en la fuente de eventos apropiada. Previamente, en la seccion 6, se hamostrado como establecer una relacion entre un JButton y un JFrame que lo contiene usando elmetodo addActionListener(). De igual forma, se pueden crear relaciones entre otros componentesSwing y las clases que reaccionan a las manipulaciones de usuarios de ellos. En el cuadro 3, cadacomponente listado en la columna izquierda esta asociado con un metodo de la columna derecha.

21

Por ejemplo, cuando se quiere que un JCheckBox responda a las pulsaciones del usuario, se puedeusar el metodo addItemListener() para registrar el JCheckBox como el tipo de objeto que puedecrear un evento ItemEvent. El argumento que se pone dentro de los parentesis de la llamda almetodo addItemListener() es el objeto que deberıa responder al evento—quizas un JFrame quecontiene el JCheckBox generador del evento. El formato es:

laFuenteDelEvento.addListenerMetodo(laClaseQueDeberaResponder);

Componente(s) Metodo(s) registradores-receptores asociados

JButton, JCheckBox, JComboBox, JText-

Field, y JRadioButton.addActionListener()

JScrollBar addAdjustmentListener()

Todos los componentes Swing. addFocusListener(), addKeyListener(),addMouseListener(), y addMouseMotion-

Listener()

JButton, JCheckBox, JComboBox, yJRadioButton.

addItemListener()

Todos los componentes JWindow y JFrame. addWindowListener()

JSlider y JCheckBox. addChangeListener()

Cuadro 3: Algunos componentes Swing y su metodos registradores-receptores asociados

Nota. Cualquier fuente de eventos puede tener multipes receptores registrados en este.Es decir,

una sola instancia de JCheckBox podrıa generar eventos ItemEvent y FocusEvent, y una sola

instancia de la clase JFrame podrıa responder a los ActionEvent generados por el JButton y a los

ItemEvents generados por el JCheckBox.

La clase del objeto que responde a un evento debe contener un metodo que acepte el objeto eventocreado por la accion del usuario. Un metodo que se ejecuta porque es llamado automaticamentecuando un evento apropiado ocurre es un manejador de evento. Es decir, cuando se registra uncomponente, tal como un JFrame, para ser un receptor para eventos generados por otro componente,como un JCheckBox, se debe escribir un metodo manejador de evento. No se puede escoger unnombre propio para los manejadores de evento—identificadores de metodos especıficos reaccionana tipos especıficos de eventos. En el cuadro 4 se listan algunos de los metodos que reaccionan aeventos.

Receptor Metodo

ActionListener actionPerformed(ActionEvent)

AdjustmentListener adjustmentValueChanged(AdjustmentEvent)

FocusListener focusGained(FocusEvent) y focusLost-

(FocusEvent)

ItemListener itemStateChanged(ItemEvent)

Cuadro 4: Metodos seleccionados que responden a eventos.

Las siguientes tareas se deben realizar cuando se declara una clase que maneja un evento:

22

La clase que maneja un evento debera implementar una interfaz receptora o extender unaclase que implemente una interfaz receptora. Por ejemplo, si un JFrame llamado MiMarco

necesita responder a pulsaciones del usuario en un JCheckBox, se podrıa escribir la siguientecabecera de clase:

public class MiMarco extends JFrame implements ItemListener

Si despues se declara una clase que extienda MiMarco, no se necesita incluir implements

ItemListener en su cabecera. La nueva clase hereda la implementacion.

Se debe registrar cada instancia de la clase manejadora de eventos como un receptor para unoo mas componentes. Por ejemplo, si MiMarco contiene un JCheckBox llamado miCheckBox,entonces dentro de la clase MiMarco se podrıa codificar:

miCheckBox.addItemListener(this);

La referencia this es a la clase en la cual miCheckBox esta declarado—en este caso, MiMarco.

Se debe escribir un metodo manejador de eventos con un identificador apropiado, como semuestra en el cuadro 4, que acepte el evento generado y reaccione a este.

9. Clases para seleccion

Otros componentes permiten al usuario hacer selecciones en un ambiente interfaz de usuario, comoJCheckBox, ButtonGroup, y JComboBox.

Clase JCheckBox

Un JCheckBox es una casilla de verificacion que consiste de una etiqueta puesta a un lado de uncuadro; se puede pulsar el cuadro para mostrar una palomita o quitarla. Se usa un JCheckBox parapermitir al usuario prender o apagar una opcion. La aplicacion DemoCheckBox, codigo 13, muestrael uso de cuatro JCheckBox.

23

1 import java . awt . ∗ ;2 import javax . swing . ∗ ;3 import java . awt . event . ∗ ;4 public class DemoCheckBox5 extends JFrame implements I t emLi s tener {6 JLabel e t i q u e t a = new JLabel ( ”¿Que deseas tomar?” ) ;7 JCheckBox c a f e = new JCheckBox ( ”Cafe” , fa l se ) ;8 JCheckBox co l a = new JCheckBox ( ”Cola” , fa l se ) ;9 JCheckBox l e c h e = new JCheckBox ( ”Leche” , fa l se ) ;

10 JCheckBox agua = new JCheckBox ( ”Agua” , fa l se ) ;11 JLabel estado = new JLabel ( ”” ) ;12 public DemoCheckBox ( ) {13 super ( ” Demostraci on CheckBox” ) ;14 s e tDe fau l tC lo seOperat ion ( JFrame .EXIT ON CLOSE ) ;15 setLayout (new FlowLayout ( ) ) ;16 e t i q u e t a . setFont (new Font ( ” Ar ia l ” , Font . ITALIC , 2 2 ) ) ;17 c a f e . addItemListener ( this ) ;18 co l a . addItemListener ( this ) ;19 l e c h e . addItemListener ( this ) ;20 agua . addItemListener ( this ) ;21 add ( e t i q u e t a ) ;22 add ( c a f e ) ;23 add ( co l a ) ;24 add ( l e c h e ) ;25 add ( agua ) ;26 add ( estado ) ;27 }28 public void itemStateChanged ( ItemEvent e ) {29 Object fuente = e . getItem ( ) ;30 JCheckBox cb = ( JCheckBox ) fuente ;31 int s e l e c c i o n = e . getStateChange ( ) ;32 i f ( s e l e c c i o n == ItemEvent .SELECTED)33 estado . setText ( ”¡Se ha s e l e c c i o n a d o ”+cb . getText ()+” ! ” ) ;34 else35 estado . setText ( ”¡Se ha quitado l a s e l e c c i on ”+cb . getText ()+” ! ” ) ;36 }37 public stat ic void main ( St r ing [ ] arguments ) {38 f ina l int FRAME WIDTH = 350 ;39 f ina l int FRAME HEIGHT = 120 ;40 DemoCheckBox ventana = new DemoCheckBox ( ) ;41 ventana . s e t S i z e (FRAME WIDTH, FRAME HEIGHT) ;42 ventana . s e t V i s i b l e ( true ) ;43 }44 }

Codigo 13: Aplicacion DemoCheckBox.

La jerarquıa de herencia de la clase JCheckBox se muestra enseguida. Los metodos mas frecuente-mente usados aparacen en el cuadro 5.

java.lang.Object

|

+--java.awt.Component

24

|

+---java.awt.Container

|

+---javax.swing.JComponent

|

+---javax.swing.AbstractButton

|

+---javax.swing.JToggleButton

|

+---javax.swing.JCheckBox

Metodo Proposito

void setText(String) pone el texto para el JCheckBox.String getText() regresa el texto JCheckBox.void setSelected(boolean) pone el estado del JCheckBox a true para seleccio-

nado o false para no seleccionado.boolean isSelected() obtiene el estado actual (marcado o desmarcado)

del JCheckBox.

Cuadro 5: Metodos JCheckBox usados frecuentemente.

Varios constructores pueden ser usados con JCheckBox. Cuando se construye un JCheckBox, sepuede escoger si se le asigna una etiqueta; si el JCheckBox aparece seleccionado, por defecto unJCheckBox no esta seleccionado. Las siguientes sentencias crean cuatro objetos JCheckBox:

Sin etiqueta y sin seleccion.

JCheckBox casilla1 = new JCheckBox();

Con etiqueta y sin seleccion.

JCheckBox casilla2 = new JCheckBox("Marcar aquı");

Con etiqueta y sin seleccion.

JCheckBox casilla3 = new JCheckBox("Marcar aquı", false );

Con etiqueta y seleccionado.

JCheckBox casilla4 = new JCheckBox("Marcar aquı", true );

Si no se quiere inicializar un JCheckBox con una etiqueta y se quiere asignar despues, o si se quierecambiar una etiqueta existente, se puede usar el metodo setText(), como sigue:

casilla1.setText("Marcar esta casilla ahora);

25

Se puede poner el estado de un JCheckBox con el metodo setSelected(); por ejemplo, se puedeusar la siguiente sentencia para asegurar que casilla1 no este seleccionada:

casilla1.setSelected(false );

El metodo isSelected() es mas util en expresiones booleanas, como en el siguiente ejemplo, lacual agrega uno a una variable contadorVotos si casilla2 esta actualmente marcada.

if (casilla2.isSelected())

++contadorVotos;

Cuando el estado de un JCheckBox cambia de marcado a no marcado, o viceversa, un eventoItemEvent es generado, y el metodo itemStateChanged() es ejecutado. Se puede usar el meto-do getItem() para determinar cual objeto genero el evento y metodo getStateChange() paradeterminar si el evento fue una seleccion o no.

El metodo getStateChange() devuelve un entero que es igual a una de las dos constantes declase—ItemEvent.SELECTED o ItemEvent.DESELECTED. En el siguiente extracto de codigo el meto-do itemStateChanged() llama al metodo getItem(), el cual regresa el objeto llamado fuente.Luego, el valor de fuente es probado con una sentencia if para determinar si este es equivalentea un objeto JCheckBox llamado casilla. Si las dos referencias son al mismo objeto, el codigodetermina si la casilla fue seleccionada o no, y en cada caso las acciones apropiadas son hechas.

public void itemStateChanged(ItemEvent e) {Object fuente = e.getItem();

if (fuente == casilla) {int seleccion = e.getStateChange():

if (seleccion == ItemEvent.SELECTED)

// sentencias que se ejecutan cuando la casilla esta seleccionada

else

// sentencias que se ejecutan cuando la casilla NO esta seleccionada

}else {

// sentencias que se ejecutan cuando la fuente del evento es otro

// componente diferente a casilla

}}

Clase ButtonGroup

Cuando se quieren opciones mutuamente exclusivas, es decir, se quiere que el usuario solo puedaseleccionar una opcion de varias, se debe crear un ButtonGroup para agrupar varios componentes,tales como los JCheckBox. Cuando se agrupan objetos JCheckBox y el usuario selecciona cual-quiera de las casillas, el resto de las casillas queda sin seleccion. La clase ButtonGroup desciendedirectamente de la clase Object y tambien es parte del paquete javax.swing.

26

Nota. Un grupo de JCheckBox en el cual un usuario puede seleccionar uno a la vez actua como un

conjunto de botones de radio, los cuales se pueden crear usando la clase JRadioButton. La clase

JRadioButton es similar a la clase JCheckBox, y se debe preferir su uso cuando se tiene una lista

de opciones de usuario mutuamente excluyente.

Para crear un ButtonGroup en un JFrame y luego agregar un JCheckBox, se deben realizar lossiguientes cuatro pasos:

1. Crear un ButtonGroup, tal como:

ButtonGroup unGrupo = new ButtonGroup();

2. Crear un JCheckBox

JCheckBox unaCasilla = new JCheckBox();

3. Agregar unaCasilla a unGrupo

unGrupo.add(unaCasilla);

4. Agregar unaCasilla al JFrame

add(unaCasilla);

Se puede crear un ButtonGroup y luego crear los objetos individuales JCheckBox, o tambien invir-tiendo el orden. Si se crea un ButtonGroup pero se olvida agregar cualquier objeto JCheckBox aeste, entonces los JCheckBox actuan como casillas individuales no exclusivas.

Un usuario puede marcar uno de los JCheckBox de un grupo pulsando con el raton en este, ocon codigo puede seleccionar un JCheckBox dentro de un ButtonGroup con una sentencia como lasiguiente:

unGrupo.setSelected(unaCasilla);

Solo un JCheckBox puede ser seleccionado dentro de un grupo. Si se asigna el estado selected aun JCheckBox dentro de un grupo, cualquier asignacion previa es dejada sin marca.

Se puede determinar cual, si hay, de los JCheckBox en un ButtonGroup esta seleccionado con elmetodo isSelected().

No se puede “limpiar la casilla” para todos los elementos que son miembros de un ButtonGroup. Sepodrıa hacer que todos los JCheckBox en un ButtonGroup inicialmente se muestren sin seleccionagregando un JCheckBox que no sea visible, usando en este el metodo setVisible(). Luego, sepodrıa usar el metodo setSelected() para marcar el JCheckBox no visible, y el resto se muestresin marca.

27

Clase JComboBox

Un JComboBox es un componente que combina dos caracterısticas: una area de visualizacion mos-trando una opcion por defecto y un cuadro de lista que contiene opciones adicionales alternas. Elarea de visualizacion contiene un boton que el usuario puede pulsar o un campo editable en el cualel usuario puede teclear. Cuando un JComboBox se muestra, la opcion por defecto es mostrada.Cuando el usuario pulsa el JComboBox, una lista de elementos alternativos cae; si el usuario selec-ciona alguno, este reemplaza el elemento del cuadro mostrado. Los usuario esperan ver las opcionesde un JComboBox en orden alfabetico. Otras formas razonables son poner las opciones en algunotro orden logico, como “pequeno”, “mediano”, y “grande”, o poniendo a los mas frecuentementeseleccionados primero.

La jerarquıa de herencia de la clase JComboBox se muestra a continuacion.

java.lang.Object

|

+--java.awt.Component

|

+---java.awt.Container

|

+---javax.swing.JComponent

|

+---javax.swing.JComboBox

Se puede construir un JComboBox usando un constructor sin argumentos y luego agregando elemen-tos, por ejemplo, String a la lista con el metodo addItem(). Las siguientes sentencias crean unJComboBox llamado opcionPrincipal que contiene tres opciones de las cuales un usuario puedeescoger:

JComboBox<String> opcionPrincipal = new JComboBox<String>();

opcionPrincipal.addItem("Ingles");

opcionPrincipal.addItem("Matematicas");

opcionPrincipal.addItem("Sociologıa");

En la declaracion del JComboBox del ejemplo previo, se usa <String> seguido del nombre de la clase.Por defecto, un JComboBox espera elementos que los elementos agregados sean del tipo Object.Usando String encerrado entre parentesis angulares se notifica al compilador que los elementosesperados en el JComboBox son String y se permite que el compilador revise por errores si elementosinvalidos son agregados. Cuando no se indica un tipo de dato para un JComboBox, el programacompila, pero un mensaje de advertencia es marcado con cada llamada al metodo addItem(). Sedice que la clase JComboBox usa genericos. La programacion con genericos es una caracterısticade los lenguajes modernos que permiten que tipos de datos multiples sean usados de forma seguracon metodos.

Otra forma de construir un JComboBox es usando un arreglo de Object como argumento para elconstructor; los elementos en el arreglo se convierten en la lista de elementos dentro del JComboBox.El siguiente codigo crea el mismo JComboBox opcionPrincipal como en el codigo precedente:

28

String[] arregloPrincipal = {"Ingles","Matematicas","Sociologıa"};JComboBox opcionPrincipal = new JComboBox(arregloPrincipal);

El cuadro 6 lista algunos metodos que se pueden usar con un objeto JComboBox. Por ejemplo,se puede usar el metodo setSelectedItem() o setSelectedIndex() para escoger uno de loselementos en un JComboBox para que sea el elemento seleccionado inicialmente. Se puede usar elmetodo getSelectedItem() o getSelectedIndex() para saber cual elemento esta actualmenteseleccionado.

Metodo Proposito

void addItem(Object) Agrega un elemento a la lista.void removeItem(Object) Quita un elemento de la lista.void removeAllItems() Quita todos los elementos de la lista.Object getItemAt(int) Regresa el elemento de la lista en la posicion indi-

cada por el ındice entero.int getItemCount() Devuelve la cantidad de elementos en la lista.int getMaximumRowCount() Regresa la cantidad maxima de elementos que el

cuadro lista puede desplegar sin una barra de des-plazamiento.

int getSelectedIndex() Da la posicion del elemento seleccionado actual-mente.

Object getSelectedItem() Da el elemento seleccionado actualmente.Object[] getSelectedObjects() Devuelve un arreglo conteniendo los Object selec-

cionados.void setEditable(boolean) Pone el campo para que sea editable o no.void setMaximumRowCount(int) Pone la cantidad de renglones en el cuadro de lista

que pueden ser mostrados a la vez.void setSelectedIndex(int) Pone el ındice en la posicion indicada por el argu-

mento.void setSelectedItem(Object) Pone el elemento seleccionado en el area de visua-

lizacion.

Cuadro 6: Metodos JComboBox usados frecuentemente.

Se puede tratar una lista de elementos en un objeto JComboBox como un arreglo; el primer ele-mento esta en la posicion cero, el segundo en la posicion uno, etc. Es adecuado usar el metodogetSelectedIndex() para determinar la posicion en la lista del elemento actualmente seleccio-nado; luego se puede usar el ındice para acceder la informacion correspondiente guardada en unarreglo paralelo. Por ejemplo, si un JComboBox llamado opcionesHistoria ha sido llenado conuna lista de eventos historicos, tales como “Declaracion de Independencia”, “Batalla de Puebla”,y “Expropiacion Petrolera” se puede codificar lo siguiente para recuperar la opcion del usuario:

int posicionSeleccion = opcionesHistoria.getSelectedIndex();

La variable posicionSeleccion guarda la posicion del elemento seleccionado, y se puede usar lavariable para acceder un arreglo de fechas para poder mostrar la fecha que corresponde al evento.Por ejemplo, si se declara lo siguiente, entondces fechas[posicionSeleccion] tiene el ano parael evento historico seleccionado:

29

int fechas = {1810,1862,1938};

Nota. Un JComboBox no tiene que guardar los elementos declarados como String; puede guardar

un arreglo de Object y mostrar los resultados del metodo toString() usados con esos objetos. Es

decir, en vez de usar arreglos paralelos para guardar eventos historicos y fechas, se podrıa designar

una clase EventoHistorico que encapsule String para el evento e int para la fecha.

Ademas de un JComboBox para el cual el usuario pulse sobre elementos presentados en una lista,se puede crear un JComboBox en el cual el usuario pueda teclear texto. Para hacer esto, se usael metodo setEditable(). Una desventaja de usar un JComboBox es que el texto que el usuarioingresa debe ser exactamente igual a un elemento en el cuadro de lista. Si el usuario introduceincorrectamente la seleccion o el uso de mayusculas/minusculas, no devuelve un valor valido lallamada del metodo getSelectedIndex(). Se puede usar una sentencia if para probar el valorregresado de getSelectedIndex(); si este es negativo, la seleccion no aparea ningun elemento enel JComboBox, y se puede generar un mensaje de error apropiado.

Actividad 5. Crea una aplicacion interactiva para un hotel incluyendo JCheckBox para las dife-rentes selecciones. El precio base para un cuarto es $2000, y un huesped puede escoger de variasopciones. Reservar un cuarto para un fin de semana agrega $1000 al precio, incluir desayuno agrega$200, e incluir un viaje en lancha agrega $750. Un huesped puede seleccionar ninguna, alguna utodos estos servicios. Cada vez que el usuario cambia la opciones del paquete, el precio es recalcu-lado.

30