5 - Cómputo

Anuncio
Topicos GUI Avanzados
H. Tejeda
Mayo 2016
Índice
1. Panel de contenido
1
2. Clase Color
4
3. Manejadores de diseño
5
4. JPanel
12
5. JScrollPane
16
6. Eventos y su manejo
18
7. Métodos de la clase AWTEvent
23
8. Manejo de eventos del ratón
23
9. Uso de menús
28
1.
Panel de contenido
La clase JFrame es una clase Java Swing contenedora de nivel superior. Las otras dos clases
contenedoras de nivel superior son JDialog y JApplet. Cada componente GUI (Graphical User
Interface) que aparece en la pantalla deberá ser parte de una jerarquı́a de contención. Una jerarquı́a de contención es un árbol de componentes que tienen un contenedor de nivel superior como
su raı́z. Cada contenedor de nivel superior tiene un panel de contenido que contiene todos los
componentes visibles en la interfaz de usuario del contenedor. El panel de contenido puede contener
directamente componentes como JButton, u otros contenedores, como JPanel, que a su vez puede
contener componentes.
1
Un contenedor de nivel superior puede tener una barra de menú. Una barra de menú es una tira
horizontal que convencionalmente está puesta en la cima de un contenedor y tiene opciones para el
usuario. La barra de menú está encima del panel de contenido. Un panel de cristal está encima
del panel de contenido. En la siguiente figura se muestra la relación entre un JFrame y su páneles
raı́z, de contenido y de cristal.
+---------------------+
| JFrame
|
|
+--------------------+
|
| Panel raı́z
|
|
|
+--------------------+
|
|
| Barra de menú
|
|
|
|--------------------|
+---|
| Panel de contenido |
|
|
+-------------------+
+---|
| Panel de cristal |
|
|
|
+---|
|
|
|
|
|
|
|
+-------------------+
Nota. En el panel de cristal residen los tool tips. Se pueden dibujar sus propios gráficos en este panel
“en la cima de” los componentes en un JFrame o JApplet. Si se agrega un MouseListener al
panel de cristal, este previene que el ratón dispare eventos en los componentes debajo del panel de
cristal en el JFrame.
Existe un panel adicional encima del panel raı́z, pero este no es usado frecuentemente por los
programadores.
Para obtener una referencia al panel de contenido de un JFrame, u otro contenedor de nivel superior,
se usa el método getContentPane(). Los métodos add() y remove() usados para agregar y quitar
componentes de objetos JFrame y el método setLayoutManager() usado para poner el manejador
de diseño tienen esas habilidades porque Java los convierte en versiones más completas. Por ejemplo,
las siguientes tres sentencias son equivalentes dentro de una clase que descienda de JFrame:
this.getContentPane().add(unBoton);
getContentPane().add(unBoton);
add(unBoton);
En la primera sentencia, this se refiere a la clase JFrame en el cual la sentencia aparece, y
getContentPane() da una referencia al panel de contenido. En la segunda sentencia, la referencia this está implicada. En la tercera sentencia, la referencia this y la llamada al método
getContentPane() están implicados.
2
No se requiere preocuparse por el panel de contenido si sólo se agregan componentes, se quitan o se
pone el manejador de diseño de un JFrame, pero se deberá referir al panel de contenido para todas
las otras acciones, tales como poner el color del fondo.
Cuando se escribe una aplicación en la cual se tenga que estar usando el panel de contenido,
es más eficiente declarar un objeto que represente el panel de contenido que estar llamando al
método getContentPane(), como se muestra en el siguiente ejemplo, donde la llamada al método
getContentPane() es hecha una vez, su referencia se guarda en una variable, y luego el nombre de
referencia es usada con la llamada al método add():
Container con = getContentPane();
con.add(boton1);
con.add(boton2);
con.add(boton3);
En la clase JFrameConContentPane, código 1, se crea un JFrame donde la operación de cierre por
defecto no fue puesta y al botón no se le asignó alguna funcionalidad, para que el ejemplo sea
sencillo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import j a v a . awt . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s JFrameConContentPane extends JFrame {
private f i n a l int TAM = 1 8 0 ;
private C o n t a i n e r con = getContentPane ( ) ;
private JButton boton = new JButton ( ” Pulsa aquı́” ) ;
public JFrameConContentPane ( ) {
super ( ” Ventana ” ) ;
s e t S i z e (TAM, TAM) ;
con . s e t L a y o u t (new FlowLayout ( ) ) ;
con . add ( boton ) ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
JFrameConContentPane marco =
new JFrameConContentPane ( ) ;
marco . s e t V i s i b l e ( true ) ;
}
}
Código 1: La clase JFrameConContentPane.
En el código 1 en la lı́nea 5 la llamada del método getContentPane() se asigna una referencia a
un Container llamado con, y luego es usada con los métodos setLayout() y add() en las lı́neas
10 y 11 respectivamente.
Cuando se quieren usar otros métodos en vez de add(), remove(), o setLayout() con un JFrame,
se debe usar un panel de contenido, como cuando se emplea el método setBackground() usado para
cambiar el color del fondo. Si este método se usa con un JFrame el usuario no verá los resultados.
3
2.
Clase Color
La clase Color define colores para ser usados en aplicaciones, por ejemplo con los métodos setBackground()
y setForeground() de la clase Component. Cuando se usa la clase Color, se debe incluir la sentencia
import java.awt.Color; al inicio del archivo de la clase.
La clase Color define constantes con nombre que representan trece colores, como se muestra en el
cuadro 1. Las constantes en Java son escritas usualmente con todas las letras en mayúsculas. Sin
embargo, los creadores de Java declararon dos constantes para cada color en la clase Color—una
versión con mayúsculas, y la otra con minúsculas. Las primeras versiones de Java contenı́an sólo
las constantes con minúsculas.
Constante
minúsculas
BLACK
BLUE
CYAN
DARK GRAY
GRAY
GREEN
LIGHT GRAY
MAGENTA
ORANGE
PINK
RED
WHITE
YELLOW
Constante
mayúsculas
black
blue
cyan
darkgray
gray
green
lightgray
magenta
orange
pink
red
white
yellow
Color
negro
azul
cian
gris obscuro
gris
verde
gris claro
magenta
naranja
rosa
rojo
blanco
amarillo
Cuadro 1: Constantes de la clase Color.
Para crear un objeto Color propio se harı́a de la siguiente forma:
Color algunColor = new Color(r, g, b);
En la sentencia previa, r, g, y b son números que representan las intensidades de rojo, verde, y azul
que se quieren en el color. El rango de los números está entre 0 y 255. Para crear el color negro se
requiere que los valores de r, g, y b sean cero, y para el color blanco es con 255. En la siguiente
sentencia se genera el color púrpura obscuro que tiene componentes para el rojo y el azul, pero
carece de verde.
Color purpuraObscuro = new Color(100, 0, 100);
Se pueden crear más de 16 millones, 224 , de colores personalizados de la forma anterior. Algunos
computadoras no pueden mostrar cada uno de los 16 millones de colores posibles; cada computadora
muestra el color más cercano que puede al color solicitado.
4
Para determinar la cantidad de los componentes rojo, verde, o azul de algún objeto Color se usan los
métodos getRed(), getGreen(), o getBlue() respectivamente. Cada uno de los métodos devuelve
un entero. Por ejemplo, para saber la cantidad de rojo en MAGENTA se usa Color.MAGENTA.getRed().
La aplicación JFrameConColor, código 2, pone el color del fondo de un panel de contenido JFrame
y los colores del frente y el fondo de un JButton.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import j a v a . awt . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s JFrameConColor extends JFrame {
private f i n a l int TAM = 1 8 0 ;
private C o n t a i n e r con = getContentPane ( ) ;
private JButton boton = new JButton ( ” Pulsa aquı́” ) ;
public JFrameConColor ( ) {
super ( ”Marco” ) ;
s e t S i z e (TAM, TAM) ;
con . s e t L a y o u t (new FlowLayout ( ) ) ;
con . add ( boton ) ;
con . setBackground ( C o l o r .YELLOW) ;
boton . setBackground ( C o l o r .RED) ;
boton . s e t F o r e g r o u n d ( C o l o r .BLUE ) ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
JFrameConColor marco =
new JFrameConColor ( ) ;
marco . s e t V i s i b l e ( true ) ;
}
}
Código 2: La aplicación JFrameConColor.
3.
Manejadores de diseño
Un manejador de diseño es un objeto que controla el tamaño y la posición (que es, el diseño) de
componentes dentro de un objeto Container. Dependiendo del manejador de diseño que se asigne a un Container este determina como sus componentes son dimensionados y posicionados. Los
manejadores de diseño son clases interfaz que son parte del JDK; estos alinean los componentes
para que ni se amontonen, ni se traslapen. Por ejemplo, el manejador de diseño FlowLayout coloca
los componentes en renglones de izquierda a derecha a través de su contenedor. Otros manejadores
de diseño ponen los componentes en columnas y renglones de tamaño igual o centran los componentes dentro de su contenedor. Cada componente que se pone dentro de un Container puede
también ser un Container por sı́ mismo, ası́ que se pueden asignar manejadores de diseño dentro de
otros. Java proporciona manejadores de diseño que van desde los muy simples, como FlowLayout
y GridLayout, los de propósito especial, como BorderLayout y CardLayout, a los muy flexibles,
como GridBagLayout y BoxLayout. En el cuadro 2 se listan cada uno de los manejadores de diseño
y las situaciones en las cuales son comúnmente empleados.
5
Manejador
BorderLayout
FlowLayout
GridLayout
CardLayout
GridBagLayout
Descripción
Usar para agregar hasta cinco componentes.
Usar para agregar componentes de izquierda a derecha;
cuando el renglón se llena se pasa automáticamente al siguiente renglón, y cada componente toma su tamaño preferente.
Usar para agregar componentes en una malla de renglones
y columnas; cada componente es del mismo tamaño.
Usar para agregar componentes que sean mostrados uno a
la vez.
Usar cuando se necesite fijar tamaño, lugar, y restricciones
de alineación para cada componente que sea agregado.
Cuadro 2: Manejadores de diseño.
Clase BorderLayout
El manejador BorderLayout es la clase manejadora por defecto para todos los páneles de contenido. Se puede usar la clase BorderLayout con cualquier contenedor que tenga 5 componentes o
menos. Cualquiera de los componentes podrı́a ser un contenedor que tenga más componentes. Con
el manejador BorderLayout los componentes llenan la pantalla en cinco regiones: norte, sur, este,
oeste y centro.
Cuando se agrega un componente a un contenedor que usa BorderLayout, el método add() usa
dos argumentos: el componente y la región a la cual este es agregado. La clase BorderLayout
proporciona cinco constantes con nombre para las regiones—BorderLayout.NORTH, .SOUTH, .EAST,
.WEST, y .CENTER—o se pueden usar los String que estas constantes representan: “North”, “South”,
“East”, “West”, o “Center”. La aplicación DemoJBorderLayout, código 3, muestra una salida donde
han sido puestos cinco botones.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import j a v a . awt . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s DemoJBorderLayout extends JFrame {
private JButton bn = new JButton ( ” Botón Norte ” ) ;
private JButton bs = new JButton ( ” Botón Sur ” ) ;
private JButton be = new JButton ( ” Botón Este ” ) ;
private JButton bo = new JButton ( ” Botón Oeste ” ) ;
private JButton bc = new JButton ( ” Botón Centro ” ) ;
private C o n t a i n e r con = getContentPane ( ) ;
public DemoJBorderLayout ( ) {
con . s e t L a y o u t (new BorderLayout ( ) ) ;
con . add ( bn , BorderLayout .NORTH) ;
con . add ( bs , BorderLayout .SOUTH) ;
con . add ( be , BorderLayout .EAST ) ;
con . add ( bo , BorderLayout .WEST) ;
con . add ( bc , ” Center ” ) ;
s e t S i z e (400 , 150);
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
DemoJBorderLayout ventana =
6
21
22
23
24
new DemoJBorderLayout ( ) ;
ventana . s e t V i s i b l e ( true ) ;
}
}
Código 3: Aplicación DemoJBorderLayout.
Nota. Cuando se usa BorderLayout, se pueden usar las constantes PAGE START, PAGE END, LINE START,
LINE END, y CENTER en vez NORTH, SOUTH, EAST, WEST, y CENTER. Las constantes dadas corresponden a posiciones que se podrı́an tener en una hoja impresa. Si se agrega la siguiente sentencia
import, se puede referir a CENTER en vez de BorderLayout.CENTER:
import static java.awt.BorderLayout.*;
Cuando se colocan cinco componentes en un contenedor y se usa BorderLayout, cada componente
llena una región entera, como se observa al ejecutar la aplicación DemoJBorderLayout. Cuando la
aplicación se ejecuta, Java determina el tamaño exacto de cada componente basado en el contenido del componente. Cuando se redimensiona un Container que use BorderLayout, las regiones
también cambian en tamaño. Si el contenedor se hace más ancho las regiones norte, sur, y centro
se hacen más anchas, pero las otras restantes no cambian. Si se incrementa la altura, las regiones
este, oeste, y centro se hacen más altas, pero las otras permanecen sin cambio.
Cuando se usa BorderLayout, no se requiere agregar componentes en cada una de las cinco regiones.
Si se agregan menos componentes, cualquier región vacı́a desaparece, y las restantes se expanden
para llenar el espacio disponible. Si cualquiera de las regiones norte, sur, este, u oeste fueron dejadas
vacı́as, el área central se expande en las áreas vacı́as. Sin embargo, si el área central es dejada, ni
la área norte, sur, este, u oeste cambia. Un error común cuando se usa BorderLayout es agregar
un componente a un panel de contenido o marco sin nombrar una región. Esto puede resultar que
algunos de los componentes no sea visible.
Clase FlowLayout
Se puede usar el manejador FlowLayout para arreglar los componentes en renglones a lo ancho
de un Container. Con un FlowLayout, cada componente que sea agregado es colocado a la derecha
de los componentes previamente agregados en un renglón; o, si el renglón actual está lleno, el
componente es puesto al inicio de un nuevo renglón.
Cuando se usa BorderLayout, los componentes que se agregan llenan sus regiones. Sin embargo,
cuando se usa FlowLayout, cada Component retiene su tamaño por defecto o tamaño preferente.
Por ejemplo, el tamaño preferente de un JButton es el tamaño que es lo suficientemente grande para
tener el texto del JButton. Cuando se usa un BorderLayout y luego se redimensiona la ventana, los
componentes cambian su tamaño porque sus regiones cambian. Cuando se usa FlowLayout y luego
se redimensiona la ventana, cada componente retiene su tamaño, pero este podrı́a obscurecerse
parcialmente o cambiar de posición.
La clase FlowLayout contiene tres constantes que se pueden usar para alinear Componentes en un
Container:
FlowLayout.LEFT
7
FlowLayout.CENTER
FlowLayout.RIGHT
Si no se indica la alineación, los componentes son alineados al centro en un Container con
FlowLayout por defecto. En la aplicación DemoJFlowLayout, código 4, un objeto FlowLayout llamado manejador es usado para poner el diseño del panel de contenido. Cuando el usuario pulsa un
botón, en las lı́neas 19—22 el método actionPerformed() cambia la alineación a la izquierda o a
la derecha usando el método setAlignment(). Al ejecutar la DemoJFlowLayout se debe observar
como los componentes JButton son reposicionados después de que se pulsa en el botón izquierdo,
y después de hacerlo en el botón derecho.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import j a v a . awt . ∗ ;
import j a v a . awt . e v e n t . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s DemoJFlowLayout extends JFrame implements A c t i o n L i s t e n e r {
private JButton b i = new JButton ( ” Botón I z q u i e r d o ” ) ;
private JButton bd = new JButton ( ” Botón Derecho ” ) ;
private C o n t a i n e r con = getContentPane ( ) ;
private FlowLayout manejador = new FlowLayout ( ) ;
public DemoJFlowLayout ( ) {
con . s e t L a y o u t ( manejador ) ;
con . add ( b i ) ;
con . add ( bd ) ;
bi . addActionListener ( this ) ;
bd . a d d A c t i o n L i s t e n e r ( t h i s ) ;
s e t S i z e (500 , 100);
}
public void a c t i o n P e r f o r m e d ( ActionEvent e v e n t ) {
Object s o u r c e = e v e n t . g e t S o u r c e ( ) ;
i f ( s o u r c e == b i )
manejador . s e t A l i g n m e n t ( FlowLayout . LEFT ) ;
else
manejador . s e t A l i g n m e n t ( FlowLayout . RIGHT ) ;
con . i n v a l i d a t e ( ) ;
con . v a l i d a t e ( ) ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
DemoJFlowLayout ventana = new DemoJFlowLayout ( ) ;
ventana . s e t V i s i b l e ( true ) ;
}
}
Código 4: Aplicación DemoJFlowLayout.
Nota. Las sentencias de las lı́neas 23 y 24 en el método actionPerformed() del código 4 llaman a
los métodos invalidate() y validate(), respectivamente. La llamada invalidate() marca el
contenedor, y cualquiera de sus padres, como necesitado de ser arreglado. La llamada validate()
causa que los componentes sean redispuestos de acuerdo al manejador nuevo asignado.
8
Clase GridLayout
Si quiere acomodar componentes en renglones y columnas del mismo tamaño, se puede usar la clase
manejador GridLayout. Cuando se crea un objeto GridLayout se indica la cantidad de renglones y
columnas deseadas, y entonces la superficie es dividida en una cuadrı́cula. Con la siguiente sentencia
se crea un GridLayout anónimo con cuatro renglones y cinco columnas en un Container llamado
con:
con.setLayout(new GridLayout(4, 5));
Cuando se agregan componentes a un GridLayout, estos son posicionados en secuencia de izquierda
a derecha a través de cada renglón. No se puede saltar una posición o indicar una posición exacta
para un componente. Sin embargo, se podrı́a agregar una etiqueta blanca para simular el salto de
una posición. Se puede también indicar una separación vertical y horizontal medida en pı́xeles, con
dos argumentos adicionales. La aplicación DemoJGridLayout, código 5, en la lı́nea 9 establece un
GridLayout con tres renglones y dos columnas, e intervalos horizontal y vertical de cinco pı́xeles
cada uno. Cinco componentes JButton son agregadas al panel de contenido recuperado del JFrame.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import j a v a . awt . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s DemoJGridLayout extends JFrame {
private JButton b1 = new JButton ( ” Botón 1 ” ) ;
private JButton b2 = new JButton ( ” Botón 2 ” ) ;
private JButton b3 = new JButton ( ” Botón 3 ” ) ;
private JButton b4 = new JButton ( ” Botón 4 ” ) ;
private JButton b5 = new JButton ( ” Botón 5 ” ) ;
private GridLayout d i s e n o = new GridLayout ( 3 , 2 , 5 , 2 ) ;
private C o n t a i n e r con = getContentPane ( ) ;
public DemoJGridLayout ( ) {
con . s e t L a y o u t ( d i s e n o ) ;
con . add ( b1 ) ;
con . add ( b2 ) ;
con . add ( b3 ) ;
con . add ( b4 ) ;
con . add ( b5 ) ;
s e t S i z e (200 , 200);
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
DemoJGridLayout ventana = new DemoJGridLayout ( ) ;
ventana . s e t V i s i b l e ( true ) ;
}
}
Código 5: Aplicación DemoJGridLayout.
Cuando se ejecuta la aplicación DemoJGridLayout, los componentes son puestos en el panel a través
de los tres renglones. Como hay seis posiciones pero sólo cinco componentes, un lugar está sin usar.
Con GridLayout, se puede indicar la cantidad de renglones y usar cero para la cantidad de columnas
para permitir que el manejador de diseño determine la cantidad de columnas, de igual forma se
9
puede indicar la cantidad de columnas y usar cero para la cantidad de renglones, para que el
manejador calcula la cantidad de renglones.
Cuando se intenta decidir entre usar un GridLayout o un FlowLayout, considerar lo siguiente:
Usar GridLayout cuando se quiere a los componentes en renglones y columnas fijas, y se
quiere que el tamaño de los componentes llene el espacio disponible.
Usar FlowLayout si se quiere que Java determine los renglones y las columnas, en vez de algo
fijo, para que los componentes retengan su tamaño “natural” para que sus contenidos sean
completamente visibles.
Clase CardLayout
El manejador CardLayout genera una pila de contenedores o componentes. Cada componente en
el grupo es referido como una carta, y cada carta puede ser cualquier tipo de componente, como un
JButton, un JLabel, o un JPanel. Se emplea un CardLayout cuando se quiere que componentes
múltiples compartan el mismo espacio de presentación.
Un manejador de cartas es creado de la clase CardLayout usando uno de dos constructores:
CardLayout() crea un diseño de cartas sin un intervalo horizontal o vertical.
CardLayout(int hInt, int vInt) crea un diseño de cartas con los intervalos horizontales
y verticales especificados. Los intervalos horizontales son colocados en las aristas izquierda y
derecha. Los intervalos verticales son colocados en las aristas de la cima y el fondo.
La aplicación DemoJCardLayout, código 6, usa un manejador CardLayout para crear una pila de
JButton que contienen las etiquetas “As de Corazones”, “Tres de Espadas”, “Reina de Tréboles”.
En el constructor de la clase, se ocupa una versión ligeramente diferente del método add() para
agregar componentes a un panel de contenido cuyo manejador de diseño es CardLayout. El formato
es:
add(unString, unContenedor);
En esta sentencia, unString representa el nombre que se quiere usar para identificar la carta
componente que es agregada.
1
2
3
4
5
6
7
8
9
10
import j a v a . awt . ∗ ;
import j a v a . awt . e v e n t . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s DemoJCardLayout extends JFrame implements A c t i o n L i s t e n e r {
private CardLayout c a r t a s = new CardLayout ( ) ;
private JButton b1 = new JButton ( ”As de Corazones ” ) ;
private JButton b2 = new JButton ( ” Tres de Espadas ” ) ;
private JButton b3 = new JButton ( ” Reina de Tré b o l e s ” ) ;
private C o n t a i n e r con = getContentPane ( ) ;
public DemoJCardLayout ( ) {
10
con . s e t L a y o u t ( c a r t a s ) ;
con . add ( ” a s ” , b1 ) ;
b1 . a d d A c t i o n L i s t e n e r ( t h i s ) ;
con . add ( ” t r e s ” , b2 ) ;
b2 . a d d A c t i o n L i s t e n e r ( t h i s ) ;
con . add ( ” r e i n a ” , b3 ) ;
b3 . a d d A c t i o n L i s t e n e r ( t h i s ) ;
s e t S i z e (200 , 100);
11
12
13
14
15
16
17
18
19
20
}
public void a c t i o n P e r f o r m e d ( ActionEvent e ) {
c a r t a s . next ( getContentPane ( ) ) ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
DemoJCardLayout ventana = new DemoJCardLayout ( ) ;
ventana . s e t V i s i b l e ( true ) ;
}
21
22
23
24
25
26
27
}
Código 6: Aplicación DemoJCardLayout.
En un programa que tenga un manejador CardLayout, un cambio de carta es disparado por
la acción del usuario. En el programa DemoJCardLayout, cada JButton dispara el método
actionPerformed(). Dentro de este método, la sentencia next(getContentPane()) cambia a la
siguiente carta del contenedor. El orden de las cartas depende del orden en cual fueron agregadas al
contenedor. Se puede también usar previous(getContentPane());, first(getContentPane());,
y last(getContentPane()); para cambiar a la carta previa, primera, y última, respectivamente.
Se puede ir a una carta especı́fica usando el nombre String asignado en la llamada al método
add(). Para la aplicación del código 6, la siguiente sentencia deberá mostrar “Tres de Espadas”
porque “tres” es usado como el primer argumento cuando el objeto b2 es agregado al panel de
contenido en el constructor DemoJCardLayout:
cards.show(getContentPane(), "tres");
Al ejecutar la aplicación DemoJCardLayout se muestra la primera carta, “As de Corazones”, y luego que el usuario pulsa una vez, aparece “Tres de Espadas”, y en la segunda pulsación “Reina de
Tréboles”. Como cada JButton es una carta, cada JButton usa el área de visualización completamente en el contenedor. Si el usuario continúa pulsando los botones carta, las cartas se ciclan en
orden.
Manejadores de diseño avanzado
El manejador GridBagLayout permite agregar componentes en lugares especı́ficos en una cuadrı́cula, al igual que se puede indicar que los componentes se expandan en múltiples renglones y columnas.
Por ejemplo, si se quiere crear un JPanel con seis JButton, en el cual dos de los JButton sean el
doble de anchos que los otros, se puede usar GridBagLayout. Esta clase es difı́cil de usar porque se
debe poner la posición y el tamaño para cada componente, y más de veinte métodos están asociados
con la clase.
11
Otra opción de manejador de diseño es el manejador BoxLayout, el cual permite que varios
componentes estén puestos verticalmente u horizontalmente. Los componentes no se reacomodan
cuando el marco es redimensionado, por ejemplo un arreglo vertical de componentes permanece
vertical a pesar del redimensionado.
Actividad 1. Crear un JFrame que use los diferentes manejadores de diseño vistos en esta sección.
4.
JPanel
Los manejadores BorderLayout, FlowLayout, GridLayout, y Cardlayout proporcionan una cantidad limitada de arreglos de pantalla si solo se pudiera colocar un solo Component en una sección
del diseño. Pero, se puede incrementar la cantidad de arreglos de componentes posibles usando la
clase JPanel. Un JPanel es un plano, superficie sin borde que puede tener componentes UI de peso
ligero. Enseguida se muestra la jerarquı́a de herencia de la clase JPanel.
java.lang.Object
|
+--java.awt.Component
|
+---java.awt.Container
|
+---javax.swing.JComponent
|
+---javax.swing.JPanel
De la figura previa, se ve que cada JPanel es un Container; ası́ que se puede usar un JPanel para
tener otros componentes UI, tales como JButton, JCheckBox, o incluso otros JPanel. Usando un
JPanel dentro de otro, se puede crear una variedad infinita de diseños de pantalla. El manejador
de diseño por defecto para cada JPanel es FlowLayout.
Para agregar un componente a un JPanel, se llama al método add() del contenedor, usando
el componente como el argumento. La aplicación JFrameConJPanels, código 7, extiende la clase
JFrame. Un JButton es agregado a un JPanel llamado panel1, y dos JButton más son agregados
a otro JPanel llamado panel2. Luego panel1 y panel2 son agregados a panel de contenido de un
JFrame.
1
2
3
4
5
6
7
8
9
10
11
12
import j a v a . awt . ∗ ;
import j a v a x . swing . ∗ ;
import s t a t i c j a v a . awt . C o l o r . ∗ ;
public c l a s s JFrameConJPanels extends JFrame {
private f i n a l int ANCHO = 2 5 0 ;
private f i n a l int ALTO = 1 2 0 ;
private JButton boton1 = new JButton ( ”Uno” ) ;
private JButton boton2 = new JButton ( ”Dos” ) ;
private JButton boton3 = new JButton ( ” Tres ” ) ;
public JFrameConJPanels ( ) {
super ( ”JFrame con J P a n e l s ” ) ;
s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
12
JPanel p a n e l 1 = new JPanel ( ) ;
JPanel p a n e l 2 = new JPanel ( ) ;
C o n t a i n e r con = getContentPane ( ) ;
con . s e t L a y o u t (new FlowLayout ( ) ) ;
con . add ( p a n e l 1 ) ;
con . add ( p a n e l 2 ) ;
p a n e l 1 . add ( boton1 ) ;
p a n e l 1 . setBackground (BLUE ) ;
p a n e l 2 . add ( boton2 ) ;
p a n e l 2 . add ( boton3 ) ;
p a n e l 2 . setBackground (RED) ;
s e t S i z e (ANCHO, ALTO) ;
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
JFrameConJPanels ventana = new JFrameConJPanels ( ) ;
ventana . s e t V i s i b l e ( true ) ;
}
}
Código 7: Aplicación JFrameConJPanels.
Al ejecutar la aplicación JFrameConJPanels se deben mostrar los dos JPanel que fueron agregados
al JFrame, el primero con un botón y color azul de fondo, y el otro con dos botones y color rojo de
fondo.
Cuando se crea un objeto JPanel, se puede usar uno de cuatro constructores disponibles. Los
diferentes constructores permiten usar valores por defecto o indicar un manejador de diseño y si
el JPanel es doble búfer. Si se indica doble búfer, la cual es la estrategia de búfer por defecto,
se indica que el espacio de memoria adicional será usado para dibujar el JPanel fuera de pantalla
cuando sea actualizado. Con doble búfer, un JPanel redibujado es mostrado sólo cuando este
está completo; esto proporciona al usuario con pantallas actualizadas que no parpadeen mientras
son redibujadas. Los cuatro constructores son los siguientes:
JPanel() crea un JPanel con doble búfer y un diseño de flujo.
JPanel(boolean esDobleBúfer) crea un JPanel con un diseño de flujo y la estrategia de
doble búfer indicada.
JPanel(LayoutManager dise~
no) crea un JPanel con el manejador de diseño indicado y doble
búfer.
JPanel(LayoutManager dise~
no, boolean esDobleBúfer) crea un JPanel con el manejador de diseño y la estrategia de búfer indicados.
Nota. Cuando se emplea doble búfer, el área de pantalla visible es llamada el área primaria, y
la imagen fuera de pantalla es llamada el búfer de respaldo. El acto de copiar los contenidos de
una área a otra es frecuentemente referida como una transferencia lineal de bloques, o blitting.
El doble búfer previene la “despedazadera”, el efecto visual que ocurre cuando se ven partes de
imágenes diferentes porque el redibujado no es lo suficientemente rápido. Como la mayorı́a de las
prestaciones, doble búfer tiene un costo de requerimientos adicionales de memoria.
13
Hay varias formas para crear un JPanel que use un manejador BorderLayout:
Se crea un diseño con nombre y se usa este como un argumento en un constructor JPanel:
BorderLayout borde = new BorderLayout();
JPanel miPanel = new JPanel(borde);
Se usa un manejador de diseño anónimo con el constructor JPanel:
JPanel miPanel = new JPanel(new BorderLayout());
Se crea un JPanel y luego se pone su manejador de diseño usando el método setLayout():
JPanel miPanel = new JPanel();
miPanel.setLayout(new BorderLayout());
Cuando un JPanel tendrá un manejador diferente de FlowLayout, es preferible especificar el manejador de diseño cuando se crea el JPanel por cuestiones de rendimiento. Si se crea el JPanel primero
y luego se cambia su manejador, se crea un objeto FlowLayout innecesario para la instanciación
original.
Se agregan componentes a un JPanel con el método add(). La aplicación JDemoMuchosPaneles,
código 8, es un JFrame que contiene cuatro JPanel y doce JButton donde cada uno muestra
un número con letras. Al panel de contenido de un JFrame automáticamente se le asigna un
BorderLayout, y a cada JPanel se le asigna un GridLayout o un FlowLayout y son colocados
en una de las regiones, dejando la región norte vacı́a. Uno o más JButton son luego colocados en
cada JPanel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import j a v a . awt . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s JDemoMuchosPaneles extends JFrame {
// Doce b o t o n e s
private JButton boton01 = new JButton ( ”Uno” ) ;
private JButton boton02 = new JButton ( ”Dos” ) ;
private JButton boton03 = new JButton ( ” Tres ” ) ;
private JButton boton04 = new JButton ( ” Cuatro ” ) ;
private JButton boton05 = new JButton ( ” Cinco ” ) ;
private JButton boton06 = new JButton ( ” S e i s ” ) ;
private JButton boton07 = new JButton ( ” S i e t e ” ) ;
private JButton boton08 = new JButton ( ”Ocho” ) ;
private JButton boton09 = new JButton ( ”Nueve” ) ;
private JButton boton10 = new JButton ( ” Diez ” ) ;
private JButton boton11 = new JButton ( ”Once” ) ;
private JButton boton12 = new JButton ( ” Doce ” ) ;
// Cuatro p a n e l e s
private JPanel p a n e l 0 1 = new JPanel (new GridLayout ( 2 , 0 ) ) ;
private JPanel p a n e l 0 2 = new JPanel (new FlowLayout ( ) ) ;
private JPanel p a n e l 0 3 = new JPanel (new FlowLayout ( ) ) ;
private JPanel p a n e l 0 4 = new JPanel (new GridLayout ( 2 , 0 ) ) ;
public JDemoMuchosPaneles ( ) {
s e t L a y o u t (new BorderLayout ( ) ) ;
14
add ( panel01 , BorderLayout .WEST) ;
add ( panel02 , BorderLayout .CENTER) ;
add ( panel03 , BorderLayout .SOUTH) ;
add ( panel04 , BorderLayout .EAST ) ;
p a n e l 0 1 . add ( boton01 ) ;
p a n e l 0 1 . add ( boton02 ) ;
p a n e l 0 1 . add ( boton03 ) ;
p a n e l 0 2 . add ( boton04 ) ;
p a n e l 0 2 . add ( boton05 ) ;
p a n e l 0 2 . add ( boton06 ) ;
p a n e l 0 3 . add ( boton07 ) ;
p a n e l 0 4 . add ( boton08 ) ;
p a n e l 0 4 . add ( boton09 ) ;
p a n e l 0 4 . add ( boton10 ) ;
p a n e l 0 4 . add ( boton11 ) ;
p a n e l 0 4 . add ( boton12 ) ;
s e t S i z e (500 , 250);
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
JDemoMuchosPaneles ventana = new JDemoMuchosPaneles ( ) ;
ventana . s e t V i s i b l e ( true ) ;
}
}
Código 8: La aplicación JDemoMuchosPaneles.
Cuando se ejecuta la aplicación JDemoMuchosPaneles el usuario puede hacer la ventana horizontalmente más grande para observar como algunos botones aparecen y se reacomodan, en particular
los que están en el JPanel que ocupa la región central.
Nota. Si se crea un programa con muchos botones y páneles como los del código 8, se deberı́a preferir
crear arreglos de los componentes en vez de manejar muchos nombres individualmente.
Nota. Los contenedores Swing, excepto JPanel, y los páneles de contenido proporcionan métodos
interfaz de programación de aplicaciones (API) que se deberı́an usar en vez del método add().
GridLayout proporciona renglones y columnas que son similares a los arreglos bidimensionales. Por
lo tanto, este se usa para mostrar arreglos de objetos. La aplicación Tablero, código 9, muestra un
patrón de ocho renglones y ocho columnas en colores alternantes. El JPanel colocado en el panel
de contenido tiene un GridLayout de ocho por ocho. 64 JPanel son declarados, y en un ciclo, uno
por uno, son instanciados y asignados a una sección de la cuadrı́cula, lı́neas 19—21. Después de que
cada conjunto de ocho JPanel es asignado a la cuadrı́cula, cuando x es divisible por 8, el color1
y el color2 son intercambiados, para que el primer renglón inicie con un cuadro azul, el segundo
inicie con un cuadro blanco, etc. Dentro de cada renglón, todos los cuadros con posición par son
llenados con un color, y los otros cuadros con otro color. Ejecutar la aplicación Tablero para ver
la salida.
1
2
3
import j a v a . awt . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s T a b l e r o extends JFrame {
15
private
private
private
private
private
private
f i n a l int RENS = 8 ;
f i n a l int COLS = 8 ;
f i n a l int SEP = 2 ;
f i n a l int NUM = RENS ∗ COLS ;
int x ;
JPanel pane = new JPanel (
new GridLayout (RENS, COLS, SEP , SEP ) ) ;
private JPanel [ ] p a n e l = new JPanel [NUM] ;
private C o l o r c o l o r 1 = C o l o r .WHITE;
private C o l o r c o l o r 2 = C o l o r .BLUE;
private C o l o r tempColor ;
public T a b l e r o ( ) {
super ( ” T a b l e r o ” ) ;
s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
add ( pane ) ;
f o r ( x = 0 ; x < NUM; ++x ) {
p a n e l [ x ] = new JPanel ( ) ;
pane . add ( p a n e l [ x ] ) ;
i f ( x % COLS == 0 ) {
tempColor = c o l o r 1 ;
color1 = color2 ;
c o l o r 2 = tempColor ;
}
i f ( x % 2 == 0 )
p a n e l [ x ] . setBackground ( c o l o r 1 ) ;
else
p a n e l [ x ] . setBackground ( c o l o r 2 ) ;
}
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
T a b l e r o ventana = new T a b l e r o ( ) ;
f i n a l int TAM = 3 0 0 ;
ventana . s e t S i z e (TAM, TAM) ;
ventana . s e t V i s i b l e ( true ) ;
}
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
}
Código 9: Aplicación Tablero.
Cuando se crea la clase Tablero, se podrı́a estar tentado a crear sólo dos JPanel, uno azul y uno
blanco, y agregarlo al panel de contenido varias veces. Sin embargo, cada componente GUI puede
ser contenido una sola vez. Si un componente ya está en un contenedor y se intenta agregar otro
contenedor, el componente será quitado del primer contenedo y luego agregado al segundo.
5.
JScrollPane
Cuando componentes en una UI Swing requieren más área de visualización que la les ha sido
asignada, se puede usar un contenedor JScrollPane para tener los componentes en una forma que
permitan al usuario desplazar partes no visibles inicialmente del panel en la vista. Un JScrollPane
tiene barras de desplazamiento a un lado o en el fondo, o en ambos, con una área de visualización
16
llamada una ventana (viewport). La siguiente figura muestra la jerarquı́a de herencia de la clase
JScrollPane.
java.lang.Object
|
+--java.awt.Component
|
+---java.awt.Container
|
+---javax.swing.JComponent
|
+---javax.swing.JScrollPanel
Hay cuatro constructores JScrollPane que son:
JScrollPane() crea un JScrollPane vacı́o en el cual las barras de desplazamiento horizontal
y vertical aparecen cuando se ocupan.
JScrollPane(Component) crea un JScrollPane que muestra el contenido del componente
indicado.
JScrollPane(Component, int, int) crea un JScrollPane que muestra el componente especificado e incluye especificaciones de las barras de desplazamiento horizontal y vertical.
JScrollPane(int, int) crea un JScrollPane con ambas especificaciones de las barras de
desplazamiento horizontal y vertical.
Cuando se crea un panel de desplazamiento simple usando el constructor sin argumentos, como en
el siguiente ejemplo, las barras de desplazamiento horizontal y vertical aparecen solo si se ocupan,
es decir, si el contenido del panel no puede ser mostrado completamente:
JScrollPane unScrollPane = new JScrollPane();
Para forzar la aparición de una barra de desplazamiento, se pueden usar las constantes definidas
en la interfaz JScrollPaneConstants:
ScrollPaneConstants.HORIZONTAL SCROLLBAR AS NEEDED
ScrollPaneConstants.HORIZONTAL SCROLLBAR ALWAYS
ScrollPaneConstants.HORIZONTAL SCROLLBAR NEVER
ScrollPaneConstants.VERTICAL SCROLLBAR AS NEEDED
ScrollPaneConstants.VERTICAL SCROLLBAR ALWAYS
ScrollPaneConstants.VERTICAL SCROLLBAR NEVER
El siguiente código crea un panel de desplazamiento que muestra una imagen llamada dibujo, una
barra de desplamiento vertical, y sin barra de desplazamiento horizontal:
17
JScrollPane desplaza = new JScrollPane(dibujo,
ScrollPaneConstants.VERTICAL SCROLLBAR ALWAYS,
ScrollPaneConstants.HORIZONTAL SCROLLBAR NEVER);
La aplicación DemoJScroll, código 10, tiene una etiqueta con una fuente grande que se agregó a
un panel. El panel de desplazamiento llamado desplaza incluye el panel y dos barras de desplazamiento.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import j a v a . awt . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s DemoJScroll extends JFrame {
private JPanel p a n e l = new JPanel ( ) ;
private J S c r o l l P a n e d e s p l a z a = new J S c r o l l P a n e ( panel ,
S c r o l l P a n e C o n s t a n t s .VERTICAL SCROLLBAR ALWAYS,
S c r o l l P a n e C o n s t a n t s .HORIZONTAL SCROLLBAR ALWAYS ) ;
private JLabel l a b e l = new JLabel ( ” Hace o c h e n t a y s i e t e ” ) ;
private Font fontGrande = new Font ( ” A r i a l ” , Font . PLAIN , 3 0 ) ;
private C o n t a i n e r con ;
public DemoJScroll ( ) {
super ( ” DemoJScroll ” ) ;
s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
con = getContentPane ( ) ;
l a b e l . s e t F o n t ( fontGrande ) ;
con . add ( d e s p l a z a ) ;
p a n e l . add ( l a b e l ) ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
f i n a l int ANCHO = 1 8 0 ;
f i n a l int ALTO = 1 0 0 ;
DemoJScroll unaVentana = new DemoJScroll ( ) ;
unaVentana . s e t S i z e (ANCHO, ALTO) ;
unaVentana . s e t V i s i b l e ( true ) ;
}
}
Código 10: Aplicación DemoJScroll.
El objeto DemoJScroll en el programa del código 10 es puesto a propósito con un tamaño suficientemente pequeño (180x100) ası́ una sola parte de la etiqueta que contiene es visible a la vez. Un
usuario puede deslizar las barras de desplazamiento para ver la etiqueta completa. Al ejecutar la
aplicación DemoJScroll muestra la ventana con barras de desplazamiento en dos lugares.
6.
Eventos y su manejo
La clase padre de todos los eventos es EventObject, la cual desciende de la clase Object. EventObject
es el padre de AWTEvent, la cual a su vez es el padre de clases de eventos especı́ficos como
ActionEvent e ItemEvent. La clase abstracta AWTEvent está contenida en el paquete java.awt.event.
La siguiente figura ilustra la jerarquı́a de herencia de estas relaciones.
18
java.lang.Object
|
+--java.util.EventObject
|
+---java.awt.AWTEvent
|
+---java.awt.event.ActionEvent
+---java.awt.event.AdjustmentEvent
+---java.awt.event.ItemEvent
+---java.awt.event.TextEvent
+---java.awt.event.ComponentEvent
|
+---java.awt.event.ContainerEvent
+---java.awt.event.FocusEvent
+---java.awt.event.PaintEvent
+---java.awt.event.WindowEvent
+---java.awt.event.InputEvent
|
+---java.awt.event.KeyEvent
+---java.awt.event.MouseEvent
En la figura previa, ComponentEvent es padre de varias clases de evento, incluyendo a InputEvent,
la cual es padre de KeyEvent y MouseEvent. El árbol para eventos tiene descendencia que va lejos,
pero los nombres de las clases son simples, y comparten tareas básicas dentro de los programas.
Por ejemplo, ActionEvent son generados por componentes donde los usuarios pueden pulsar, como
JButton y JCheckBox; TextEvent son generados por componentes en los cuales el usuario ingresa
texto, tales como JTextField. MouseEvent incluyen determinar la posición del apuntador del ratón
y la distinción entre una pulsación simple y una doble. El cuadro 3 lista algunas acciones comunes
del usuario y los eventos que son generados por ellos.
Acción del usuario
Pulsar un botón
Pulsar un componente
Pulsar un elemento en un cuadro de lista
Pulsar un elemento en una casilla de verificación
Cambiar texto en un campo de texto
Abrir una ventana
Iconificar una ventana
Presionar una tecla
Tipo de evento resultante
ActionEvent
MouseEvent
ItemEvent
ItemEvent
TextEvent
WindowEvent
WindowEvent
KeyEvent
Cuadro 3: Ejemplos de acciones del usuario y sus tipos de eventos resultantes.
Como ActionEvent involucra al ratón, es fácil confundirlo con MouseEvent. Si se está interesado
en ActionEvent, la atención está en los cambios de un componente, por ejemplo, un JButton en
un JFrame siendo presionado; si se está interesado en MouseEvent, el foco está en lo que el usuario
hace manualmente con el ratón, por ejemplo, pulsar el botón izquierdo del ratón.
19
Cuando se escriben programas con GUI, siempre se están manejando eventos que se originan con
el ratón o teclas en componentes o contenedores especı́ficos. El sistema operativo notifica al usuario cuando un AWTEvent ocurre, por ejemplo, cuando el ratón es pulsado. Se pueden ignorar los
AWTEvent, y por lo tanto no producirán algún efecto.
Para tener cuidado de los eventos se puede implementar una interfaz apropiada para la clase. Cada
clase evento mostrada en el cuadro 3 tiene una interfaz receptora asociada con este, ası́ para cada
clase evento, <nombre>Evento, hay una interfaz similar llamada <nombre>Listener. Por ejemplo,
ActionEvent tiene una interfaz ActionListener. La clase MouseEvent tiene un receptor adicional
además de MouseListener que es MouseMotionListener.
Cada método de la interfaz <nombre>Listener tiene el tipo de regreso void, y cada uno toma
un argumento: un objeto que es una instancia de la correspondiente clase <nombre>Evento. Ası́,
la interfaz ActionListener tiene un método manejador de evento llamado actionPerformed(),
y su cabecera es void actionPerformed(ActionEvent e). Cuando una acción sucede, el método
actionPerformed() se ejecuta, y e representa una instancia de aquel evento.
En vez de implementar una clase receptora, se puede extender una clase adaptadora. Una clase
adaptadora implementa todos los métodos en una interfaz, con un cuerpo vacı́o para cada método.
Por ejemplo, la clase MouseAdapter da un método vacı́o para todos los métodos contenidos en
MouseListener. La ventaja de extender una clase adaptadora en vez de implementar una interfaz
receptora es que sólo se necesita escribir los métodos que se quieren usar. Si un receptor tiene un
sólo método, no hay necesidad de un adaptador, como con ActionListener.
Si se usa un receptor o un adaptador, se crea un manejador de evento cuando se escribe código para
los métodos receptores; es decir, se le dice a la clase como manejar el evento. Después de crear el
manejador, se debe registrar una instancia de la clase con el componente que se quiere que el evento
afecte. Para cualquier <name>Listener, se debe usar la forma object.add<nombre>Listener(Component) para registrar un objeto con el Component que escuchará objetos. Los métodos add<nombre>Listener(), tales como addActionListener() y addItemListener(), todos trabajan de la
misma forma. Ellos registran un receptor con un Component, regresan void, y toman un objeto
<nombre>Listener como un argumento. Por ejemplo, si un JFrame es un ActionListener y contiene un JButton llamado presióname, entonces la siguiente sentencia registra este JFrame como
un receptor para el JButton presióname:
presióname.addActionListener(this);
El cuadro 4 lista los eventos con sus receptores y manejadores.
Ejemplo de manejo-evento KeyListener
Se usa la interfaz KeyListener cuando se está interesado en acciones que el usuario inicia desde el teclado. La interfaz KeyListener contiene tres métodos: keyPressed(), keyTyped(), y
keyReleased(). Para la mayorı́a de las aplicaciones de teclado, no es importante si se realiza
la acción cuando el usuario primero presiona una tecla, durante la presión de la tecla, o hasta
que la tecla sea soltada; probablemente estos eventos ocurren en secuencia rápida. Sin embargo,
en aquellas ocasiones que no se quiere tomar acción mientras el usuario mantiene presionada la
20
Evento
ActionEvent
ItemEvent
TextEvent
AdjustmentEvent
Receptor(es)
ActionListener
ItemListener
TextListener
AdjustmentListener
ContainerEvent
ContainerListener
ComponentEvent
ComponentListener
FocusEvent
FocusListener
MouseEvent
MouseListener
MouseMotionListener
KeyListener
KeyEvent
WindowEvent
WindowListener
MouseWheelEvent
MouseWheelListener
Manejador(es)
actionPerformed(ActionEvent)
itemStateChanged(ItemEvent)
textValueChanged(TextEvent)
adjustmentValueChanged(AdjustmentEvent)
componentAdded(ContainerEvent)
componentRemoved(ContainerEvent)
componentMoved(ComponentEvent)
componentHidden(ComponentEvent)
componentResized(ComponentEvent)
componentShown(ComponentEvent)
focusGained(FocusEvent)
focusLost(FocusEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mouseClicked(MouseEvent)
mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
keyPressed(KeyEvent)
keyTyped(KeyEvent)
keyReleased(KeyEvent)
windowActivated(WindowEvent)
windowClosing(WindowEvent)
windowClosed(WindowEvent)
windowDeiconified(WindowEvent)
windowIconified(WindowEvent)
windowOpened(WindowEvent)
mouseWheelMoved(MouseWheelEvent)
Cuadro 4: Ejemplos de acciones del usuario y sus tipos de eventos resultantes.
21
tecla, se pueden colocar las acciones en el método keyReleased(). Lo mejor es usar el método
keyTyped() cuando se quiere descubrir que carácter fue tecleado. Cuando el usuario presiona una
tecla que no genera un carácter, tal como una tecla función, llamadas a veces una tecla acción,
keyTyped() no es ejecutada. Los métodos keyPressed() y keyReleased() dan las únicas formas
para obtener información acerca de las teclas que no generan caracteres. La clase KeyEvent tiene
constantes conocidas como códigos de teclas virtuales que representan las teclas que han sido
presionadas. Por ejemplo, cuando se teclea A, dos códigos de teclas virtuales son generados: Cambio
y “a”. Las constantes de códigos de teclas virtuales tienen nombres como VK SHIFT y VK ALT. La
aplicación DemoJKeyFrame, código 11 usa el método keyTyped() para saber cual fue la última tecla
presionada por el usuario.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import j a v a . awt . ∗ ;
import j a v a . awt . e v e n t . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s DemoJKeyFrame extends JFrame implements K e y L i s t e n e r {
private JLabel a v i s o = new JLabel ( ” P r e s i o n a r t e c l a s en e l campo de t e x t o : ” ) ;
private JLabel e t i q u e t a S a l i d a = new JLabel ( ) ;
private J T e x t F i e l d t e x t F i e l d = new J T e x t F i e l d ( 1 0 ) ;
public DemoJKeyFrame ( ) {
s e t T i t l e ( ”Marco DemoJKeyFrame” ) ;
s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
add ( a v i s o , BorderLayout .NORTH) ;
add ( t e x t F i e l d , BorderLayout .CENTER) ;
add ( e t i q u e t a S a l i d a , BorderLayout .SOUTH) ;
t e x t F i e l d . addKeyListener ( this ) ;
}
public void keyTyped ( KeyEvent e ) {
char c = e . getKeyChar ( ) ;
e t i q u e t a S a l i d a . s e t T e x t ( ” Ú l t i m a t e c l a p r e s i o n a d a : ” + c ) ;
}
public void k e y P r e s s e d ( KeyEvent e ) { }
public void k e y R e l e a s e d ( KeyEvent e ) { }
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
DemoJKeyFrame ventanaKey = new DemoJKeyFrame ( ) ;
f i n a l int ANCHO = 2 5 0 ;
f i n a l int ALTO = 1 0 0 ;
ventanaKey . s e t S i z e (ANCHO, ALTO) ;
ventanaKey . s e t V i s i b l e ( true ) ;
}
}
Código 11: Aplicación DemoJKeyFrame.
Nota. Los programadores Java llaman a los eventos keyTyped() eventos de “nivel–alto” porque
no dependen de la plataforma o el diseño del teclado. En cambio, los eventos keyPressed() y
keyReleased() son eventos “nivel–bajo” y dependen de la plataforma y el diseño del teclado
Al ejecutar la aplicación DemoJKeyFrame se muestra un indicador en el área del borde norte que
pide al usuario teclear en el campo de texto del área central. Con cada tecla presionada, el método
keyTyped() cambia la etiqueta en el área de borde sur del marco para mostrar la tecla que fue
generada por el KeyEvent más reciente.
22
7.
Métodos de la clase AWTEvent
Además de los métodos manejadores incluidos con las interfaces receptoras de eventos, las clases
AWTEvent por sı́ mismas contienen otros métodos que devuelven información acerca de un evento.
Por ejemplo, la clase ComponentEvent tiene el método getComponent() que permite determinar
cual de los múltiples Component generó el evento. La clase WindowEvent tiene un método similar,
getWindow(), que devuelve la Window que es la fuente de un evento. El cuadro 5 lista algunos
métodos útiles para varias clases de eventos. Todos los Component tienen estos métodos:
addComponentListener()
addFocusListener()
addMouseListener()
addMouseMotionListener()
Se puede llamar cualquiera de los métodos listados en el cuadro 5 usando el formato objeto-puntométodo que se usa con todos los métodos de instancia. Por ejemplo, si se tiene un KeyEvent llamado
eventoEntrada y un entero llamado valorUnicode, la siguiente sentencia es válida:
valorUnicode = eventoEntrada.getKeyChar();
Cuando se usa un evento, se puede usar cualquiera de los métodos de evento, y por la herencia, se
pueden también usar métodos que pertenezcan a cualquier superclase del evento. Por ejemplo, cualquier KeyEvent tiene acceso a los métodos InputEvent, ComponentEvent, AWTEvent, EventObject,
y Object, al igual que los métodos KeyEvent.
Coordenadas x e y
El cuadro 5 refiere las coordenadas x-y de un apuntador de ratón. Una ventana o marco consiste de
una cantidad de pı́xeles horizontales y verticales en la pantalla. Cualquier componente que se ponga
en la pantalla tiene un posición horizontal, o eje x al igual que una posición vertical, eje y en la
ventana. La esquina superior izquierda de cualquier pantalla es la posición 0,0. El primer valor, o
coordenada x, se incrementa conforme se viaja de izquierda a derecha a través de la ventana. El
segundo valor, coordenada y, se incrementa conforme se va de arriba hacia abajo.
8.
Manejo de eventos del ratón
La interfaz MouseMotionListener proporciona los métodos llamados mouseDragged() y mouseMoved() que detectan el ratón siendo movido o arrastrando a través de una superficie componente.
La interfaz MouseListener da los métodos mousePressed(), mouseClicked(), y mouseReleased()
que son análogos a los métodos evento teclado keyPressed(), keyTyped(), y keyReleased()
23
Clase
EventObject
Método
Object getSource()
ComponentEvent
Component getComponent()
WindowEvent
Window getWindow()
ItemEvent
Object getItem()
int getStateChange()
InputEvent
int getModifiers()
int getWhen()
boolean isAltDown()
boolean isControlDown()
boolean isShiftDown()
KeyEvent
getKeyChar()
MouseEvent
getButton()
getClickCount()
int getX()
int getY()
Point getPoint()
Propósito
Regresa la referencia Object involucrada en el evento.
Regresa la referencia Component involucrada en el evento.
Regresa la referencia Window involucrada en el evento.
Regresa la referencia Object que fue
seleccionada o deseleccionada.
Regresa
un
entero
llamado
ItemEvent.SELECTED
o
ItemEvent.DESELECTED.
Regresa un entero para indicar cual
botón del ratón fue pulsado.
Regresa un tiempo indicando cuando
el evento ocurrió.
Regresa si la tecla Alt fue presionada
cuando el evento ocurrió.
Regresa si la tecla Ctrl fue presionada cuando el evento ocurrió.
Regresa si la tecla Shift fue presionada cuando el evento ocurrió.
Regresa el carácter Unicode ingresado del teclado.
Regresa cual, si hay alguno, de
los botones del ratón ha cambido,
usa los campos NOBUTTON, BUTTON1,
BUTTON2, y BUTTON3.
Regresa el número de pulsaciones del
ratón; permite identificar las dobles
pulsaciones del usuario.
Regresal la coordenada x del apuntador del ratón.
Regresal la coordenada y del apuntador del ratón.
Regresa el objeto Point que contiene
las coordenadas x e y del lugar del
ratón.
Cuadro 5: Métodos útiles de clases de eventos.
24
respectivamente. Sin embargo, con un ratón se está más interesado que sólo el botón presionado; en ocasiones se quiere saber a dónde el ratón apunta. Los métodos adicionales de la interfaz
mouseEntered() y mouseExited() informan cuando el usuario posiciona el ratón encima de un
componente o mueve el ratón fuera de un componente. La interfaz MouseInputListener implementa todos los métodos de las interfaces MouseListener y MouseMotionListener; sin embargo
no tiene métodos propios, pero es conveniente cuando se quiere manejar muchos tipos diferentes de eventos de ratón. Los cuadros 6 y 7 muestran los métodos de las clases MouseListener y
MouseMotionListener, respectivamente.
Método
void mouseClicked(MouseEvent e)
void mouseEntered(MouseEvent e)
void mouseExited(MouseEvent e)
void mousePressed(MouseEvent e)
void mouseReleased(MouseEvent e)
Descripción
Invocado cuando el botón del ratón ha sido pulsado (presionado y soltado) en un
componente.
Invocado cuando el apuntador del ratón
ingresa en un componente.
Invocado cuando el apuntador del ratón
sale de un componente.
Invocado cuando un botón del ratón ha
sido presionado en un componente.
Invocado cuando un botón del ratón ha
sido soltado en un componente.
Cuadro 6: Métodos MouseListener.
Método
void mouseDragged(MouseEvent e)
void mouseMoved(MouseEvent e)
Descripción
Invocado cuando el apuntador del ratón
es presionado en un componente y luego
arrastrado.
Invocado cuando el apuntador del ratón
ha sido movido en un componente pero
sin algún botón presionado.
Cuadro 7: Métodos MouseMotionListener.
Nota. La interfaz MouseWheelListener tiene sólo un método llamado mouseWheelMoved(), y este
acepta un argumento MouseWheelEvent.
Cada uno de los métodos de los cuadros 6 y 7 aceptan un argumento MouseEvent. Un MouseEvent
es el tipo de evento generado por la manipulación del ratón. En la siguiente figura se muestra la
jerarquı́a de herencia de la clase MouseEvent. De ese diagrama, se puede ver que un MouseEvent
es un tipo de InputEvent, el cual es un tipo de ComponentEvent. La clase MouseEvent contiene
muchos métodos de instancia y campos que son útiles en describir eventos generados por el ratón.
El cuadro 8 lista algunos de los métodos más útiles de la clase MouseEvent, y el cuadro 9 lista
algunos campos.
25
java.lang.Object
|
+--java.util.EventObject
|
+---java.awt.AWTEvent
|
+---java.awt.event.ComponentEvent
|
+---java.awt.event.InputEvent
|
+---java.awt.event.MouseEvent
Método
int getButton()
int getClickCount()
int getX()
int getY()
Descripción
Regresa cual, si hay, de los botones del
ratón ha cambiado su estado; usa los
campos NOBUTTON, BUTTON1, BUTTON2, y
BUTTON3.
Regresa la cantidad de pulsaciones del
ratón asociado con el evento actual.
Regresa la posición-x horizontal del evento relativa al componente fuente.
Regresa la posición-y vertical del evento
relativa al componente fuente.
Cuadro 8: Métodos útiles de la clase MouseEvent.
Campo
static int BUTTON1
static int BUTTON2
static int BUTTON3
static int NOBUTTON
static
static
static
static
int
int
int
int
MOUSE
MOUSE
MOUSE
MOUSE
CLICKED
DRAGGED
ENTERED
EXITED
Descripción
Indica botón de ratón #1; usado
getButton().
Indica botón de ratón #2; usado
getButton().
Indica botón de ratón #3; usado
getButton().
Indica ningún botón de ratón; usado
getButton().
El evento “ratón pulsado”.
El evento “ratón arrastrado”.
El evento “ratón ingresado”.
El evento “ratón salido”.
por
por
por
por
Cuadro 9: Algunos campos útiles de la clase MouseEvent.
La aplicación JFrameMouseAction, código 12, muestra varios de los métodos receptores y de eventos
del ratón. JFrameMouseAction extiende JFrame, y como implementa la interfaz MouseListener,
debe incluir todos los cinco métodos—mouseClicked(), mouseEntered(), mouseExited(), mousePressed(), y mouseReleased()—a pesar de que no hay acciones incluidas en los métodos mousePressed() y mouseReleased().
26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import j a v a . awt . ∗ ;
import j a v a . awt . e v e n t . ∗ ;
import j a v a x . swing . ∗ ;
import s t a t i c j a v a . awt . e v e n t . MouseEvent . ∗ ;
public c l a s s JFrameMouseAction extends JFrame implements M o u s e L i s t e n e r {
private int x , y ;
private JLabel e t i q u e t a = new JLabel ( ” Haciendo a l g o con e l r a t ón” ) ;
S t r i n g mensj = ” ” ;
public JFrameMouseAction ( ) {
s e t T i t l e ( ” A c c i o n e s d e l Ratón” ) ;
s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
s e t L a y o u t (new FlowLayout ( ) ) ;
addMouseListener ( t h i s ) ;
add ( e t i q u e t a ) ;
}
public void mouseClicked ( MouseEvent e ) {
int cualBoton = e . getButton ( ) ;
mensj = ” Se p r e s i o n ó e l ” ;
i f ( cualBoton == BUTTON1)
mensj += ” botón 1 . ” ;
e l s e i f ( cualBoton == BUTTON2)
mensj += ” botón 2 . ” ;
else
mensj += ” botón 3 . ” ;
mensj += ” Se e s t á en l a p o s i c i ón ” +
e . getX ( ) + ” , ” + e . getY ( ) + ” . ” ;
i f ( e . g e t C l i c k C o u n t ( ) == 2 )
mensj += ” Hizo una d o b l e p u l s a c i ón . ” ;
else
mensj += ” Hizo una p u l s a c i ón s i m p l e . ” ;
e t i q u e t a . s e t T e x t ( mensj ) ;
}
public void mouseEntered ( MouseEvent e ) {
mensj = ” Se e n t r ó a l marco . ” ;
e t i q u e t a . s e t T e x t ( mensj ) ;
}
public void mouseExited ( MouseEvent e ) {
mensj = ” Se s a l i ó d e l marco . ” ;
e t i q u e t a . s e t T e x t ( mensj ) ;
}
public void mousePressed ( MouseEvent e ) { }
public void mouseReleased ( MouseEvent e ) { }
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
JFrameMouseAction ventana = new JFrameMouseAction ( ) ;
f i n a l int ANCHO = 7 5 0 ;
f i n a l int ALTO = 3 0 0 ;
ventana . s e t S i z e (ANCHO, ALTO) ;
ventana . s e t V i s i b l e ( true ) ;
}
}
Código 12: La aplicación JFrameMouseAction.
Al ejecutar la aplicación JFrameMouseAction muestra mensaje conforme el usuario genera acciones
27
del ratón. Al inicio de la clase, en la lı́nea 6, dos enteros son declarados para guardar las coordenadas
x-y de la posición del ratón. Un JLabel y un String son también declarados, en las lı́neas 7 y 8,
para guardar mensajes que informan al usuario de las acciones hechas con el ratón. El constructor,
lı́neas 9–15, pone el tı́tulo del JFrameMouseAction, pone la operación de cierra, pone el manejador
de diseño, habilita al marco para escuchar los eventos del ratón, y agrega el JLabel al JFrame.
La mayorı́a de las acciones ocurren en el método mouseClicked(). En este método se construye
un String que al final es asignado al JLabel. Las mismas acciones podrı́an haber sido colocadas
en el método mousePressed() o mouseReleased(). Dentro del método mouseClicked(), el objeto
MouseEvent llamado e es usado varios veces. Se usa con el método getButton() para determinar
cual botón del ratón el usuario ha pulsado, con getX() y getY() para recuperar la posición del
ratón donde se pulsó, y con getClickcount() para distinguir entre una pulsación simple y una
doble.
El usuario es notificado cuando el apuntador del ratón ha “entrado” al JFrame, y también cuando ha
“salido” mediante mensajes diferentes generados por los métodos mouseEntered() y mouseExited()
respectivamente.
El método main() al final de la clase crea una instancia de la clase JFrameMouseAction y fija su
tamaño y visibilidad.
9.
Uso de menús
Los menús son listas de opciones; estas son caracterı́sticas agregadas en programas GUI. Las aplicaciones de usuario son usadas para ver una barra de menú horizontal a lo largo de la parte superior
del marco, y se espera que se puedan pulsar estas opciones para producir listas descendentes que
muestran más opciones. La lista horizontal de varias JMenu es una JMenuBar. Cada JMenu puede contener opciones, llamadas JMenuItems, o puede contener submenús que también son JMenu.
La aplicación JFrameMenu, código 13, muestra un JFrame que muestra el uso de los siguientes
componentes:
Un JMenuBar que contiene dos JMenu llamados archivo y colores.
Tres elementos dentro del JMenu colores: claro, oscuro, blanco. oscuro y blanco son
JMenuItems. claro es un JMenu que tiene un submenu. Se puede decir que claro es un
submenú porque una flecha está a la derecha de su nombre, y cuando el ratón se pone encima
de claro, dos JMenuItem adicionales aparecen: rosa y amarillo.
Para generar la salida dada por la ejecución de la aplicación JFrameMenu, un conjunto de objetos
JMenuBar, JMenu, y JMenuItem fueron creados y puestos juntos en etapas. Se crean cada uno de
los componentes como sigue:
1. Crear un JMenuBar:
JMenuBar BarraPrinc = new JMenuBar();
2. Crear los dos JMenu que son parte del JMenuBar:
28
JMenu archivo = new JMenu("Archivo");
JMenu colores = new JMenu("Colores");
3. Los tres componentes dentro del JMenu colores son creados como sigue:
JMenu claro = new JMenu("Claro");
JMenuItem oscuro = new JMenuItem("Oscuro");
JMenuItem blanco = new JMenuItem("Blanco");
4. Los dos JMenuItem que son partes del JMenu Claro son creados ası́:
JMenuItem rosa = new JMenuItem("Rosa");
JMenuItem amarillo = new JMenuItem("Amarillo");
5. Después de que los componentes son creados, se ensamblan. Se agrega el JMenuBar a un
JFrame usando el método setJMenuBar() como sigue:
setJMenuBar(BarraPrinc);
Usando el método setJMenuBar() asegura que la barra de menú es anclada a la cima del
marco y parece una barra de menú convencional. Observar que el JMenuBar no es agregado
al panel de contenido del JFrame; este es agregado al JFrame por sı́ mismo.
6. Los JMenu son agregados al JMenuBar usando el método add(). Por ejemplo:
BarraPrinc.add(archivo);
BarraPrinc.add(colores);
7. Un submenú y dos JMenuItem son agregados al menú colores como se muestra enseguida:
colores.add(claro);
colores.add(oscuro);
colores.add(blanco);
8. Un submenú puede contener sus propios JMenuItem. Por ejemplo, el JMenu claro que es parte
del menú colores contiene sus dos objetos propios JMenuItem:
claro.add(rosa);
claro.add(amarillo);
El código 13 muestra un programa completo que crea un marco con un saludo y el JMenu descrito
previamente.
29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import j a v a . awt . ∗ ;
import j a v a . awt . e v e n t . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s JFrameMenu extends JFrame implements A c t i o n L i s t e n e r {
private JMenuBar B a r r a P r i n c = new JMenuBar ( ) ;
private JMenu a r c h i v o = new JMenu ( ” Archivo ” ) ;
private JMenu c o l o r e s = new JMenu ( ” C o l o r e s ” ) ;
private JMenuItem s a l i r = new JMenuItem ( ” S a l i r ” ) ;
private JMenu c l a r o = new JMenu ( ” C l a r o ” ) ;
private JMenuItem o s c u r o = new JMenuItem ( ” Oscuro ” ) ;
private JMenuItem b l a n c o = new JMenuItem ( ” Blanco ” ) ;
private JMenuItem r o s a = new JMenuItem ( ” Rosa ” ) ;
private JMenuItem a m a r i l l o = new JMenuItem ( ” A m a r i l l o ” ) ;
private JLabel e t i q u e t a = new JLabel ( ” Hola ” ) ;
public JFrameMenu ( ) {
s e t T i t l e ( ” Demostración de Menú” ) ;
s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
s e t L a y o u t (new FlowLayout ( ) ) ;
setJMenuBar ( B a r r a P r i n c ) ;
B a r r a P r i n c . add ( a r c h i v o ) ;
B a r r a P r i n c . add ( c o l o r e s ) ;
a r c h i v o . add ( s a l i r ) ;
c o l o r e s . add ( c l a r o ) ;
c o l o r e s . add ( o s c u r o ) ;
c o l o r e s . add ( b l a n c o ) ;
c l a r o . add ( r o s a ) ;
c l a r o . add ( a m a r i l l o ) ;
s a l i r . addActionListener ( this ) ;
oscuro . addActionListener ( this ) ;
blanco . addActionListener ( this ) ;
rosa . addActionListener ( this ) ;
amarillo . addActionListener ( this ) ;
add ( e t i q u e t a ) ;
e t i q u e t a . s e t F o n t (new Font ( ” A r i a l ” , Font .BOLD, 2 6 ) ) ;
}
public void a c t i o n P e r f o r m e d ( ActionEvent e ) {
Object s o u r c e = e . g e t S o u r c e ( ) ;
C o n t a i n e r con = getContentPane ( ) ;
i f ( s o u r c e == s a l i r )
System . e x i t ( 0 ) ;
e l s e i f ( s o u r c e == o s c u r o )
con . setBackground ( C o l o r .BLACK) ;
e l s e i f ( s o u r c e == b l a n c o )
con . setBackground ( C o l o r .WHITE) ;
e l s e i f ( s o u r c e == r o s a )
con . setBackground ( C o l o r . PINK ) ;
else
con . setBackground ( C o l o r .YELLOW) ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
JFrameMenu ventana = new JFrameMenu ( ) ;
f i n a l int ANCHO = 2 5 0 ;
f i n a l int ALTURA = 2 0 0 ;
ventana . s e t S i z e (ANCHO, ALTURA) ;
ventana . s e t V i s i b l e ( true ) ;
}
30
}
Código 13: La aplicación JFrameMenu.
En la aplicación JFrameMenu, cada JMenuItem se convierte en una fuente para una ActionEvent, y
al JFrame se le asigna el papel de receptor para cada uno. El método actionPerformed() determina
la fuente de cualquier evento generado. Si el usuario selecciona la opción Salir del menú Archivo,
la aplicación termina. Si el usuario selecciona cualquiera de los colores del menú Colores, el color
del fondo del JFrame es modificado en consecuencia.
Uso de objetos JCheckBoxMenuItem y JRadioButtonMenuItem
Las clases JCheckBoxMenuItem y JRadioButtonMenuItem derivan de la clase JMenuItem. Cada una
proporciona elementos de menú más especı́ficos como sigue:
Los objetos JCheckBoxMenuItem aparecen seguido de una casilla de verificación. Un elemento
puede ser seleccionado, mostrando una marca de verificación en la casilla, o no. Se usan los
elementos de casilla de verificación para apagar o encender opciones.
Los objetos JRadioButtonMenuItem aparecen seguidos de un botón circular de radio. Se
espera que los botones de radio sean mutuamente excluyentes, ası́ que se hacen parte de un
ButtonGroup. Luego, cuando cualquiera de los botones de radio es seleccionado, todos los
otros no quedan seleccionados.
El estado de un JCheckBoxMenuItem o un JRadioButtonMenuItem puede ser determinado con el
método isSelected(), y se puede modificar el estado de la casilla de verificación con el método
setSelected().
La aplicación JFrameMenu2, código 14, muestra dos JCheckBoxMenuItem y tres JRadioButtonMenuItem
han sido agregados a un JMenu. A los controles no se les ha asignado todavı́a alguna tarea.
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import j a v a . awt . ∗ ;
import j a v a . awt . e v e n t . ∗ ;
import j a v a x . swing . ∗ ;
public c l a s s JFrameMenu2 extends JFrame {
private JMenuBar B a r r a P r i n c = new JMenuBar ( ) ;
private JMenu menu1 = new JMenu ( ” Archivo ” ) ;
private JCheckBoxMenuItem v e r i f i c a 1 = new
JCheckBoxMenuItem ( ” Marcar c a j a A” , true ) ;
private JCheckBoxMenuItem v e r i f i c a 2 = new
JCheckBoxMenuItem ( ” Marcar c a j a B” ) ;
private JRadioButtonMenuItem r a d i o 1 = new
JRadioButtonMenuItem ( ” Radio o p c i ón 1 ” , true ) ;
private JRadioButtonMenuItem r a d i o 2 = new
JRadioButtonMenuItem ( ” Radio o p c i ón 2 ” ) ;
private JRadioButtonMenuItem r a d i o 3 = new
JRadioButtonMenuItem ( ” Radio o p c i ón 3 ” ) ;
private ButtonGroup grupo = new ButtonGroup ( ) ;
public JFrameMenu2 ( ) {
s e t T i t l e ( ” Demostración de Menú s −− 2 ” ) ;
s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
s e t L a y o u t (new FlowLayout ( ) ) ;
setJMenuBar ( B a r r a P r i n c ) ;
B a r r a P r i n c . add ( menu1 ) ;
menu1 . add ( v e r i f i c a 1 ) ;
menu1 . add ( v e r i f i c a 2 ) ;
menu1 . a d d S e p a r a t o r ( ) ;
menu1 . add ( r a d i o 1 ) ;
menu1 . add ( r a d i o 2 ) ;
menu1 . add ( r a d i o 3 ) ;
grupo . add ( r a d i o 1 ) ;
grupo . add ( r a d i o 2 ) ;
grupo . add ( r a d i o 3 ) ;
}
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
JFrameMenu2 ventana = new JFrameMenu2 ( ) ;
f i n a l int ANCHO = 3 0 0 ;
f i n a l int ALTO = 2 0 0 ;
ventana . s e t S i z e (ANCHO, ALTO) ;
ventana . s e t V i s i b l e ( true ) ;
}
}
Código 14: Aplicación JFrameMenu2.
Uso de addSeparator()
Al ejecutar la aplicación JFrameMenu2 y pulsar en la opción Archivo del menú, se observa una
lı́nea horizontal que separa en grupos las opciones. Este separador es agregado usando el método
addSeparator() en la lı́nea 27 del código 14. El separador no cambia la funcionalidad del menú;
simplemente hace el ménu más organizado visualmente para el usuario.
32
Uso de setMnemonic()
Un mnemónico ó nemónico es una tecla que causa que un elemento de menú pueda ser escogido
por esta. Se puede usar el método setMnemonic() para dar una tecla de menú breve para cualquier
elemento visible del menú. Por ejemplo, cuando se agrega la siguiente sentencia al constructor
JFrameMenu2, en el código 14, se permite usar una combinación de teclas para acceder la opción:
menu1.setMnemonic(’A’);
El nemónico para el menú Archivo es puesta a A, ası́ la A en Archivo está subrayada. Cuando un
usuario presiona Alt+A en el teclado, el resultado es el mismo si el usuario hubiera pulsado Archivo
en el menú: la lista de menú es abierta y mostrada.
Se deberán usar diferentes nemónicos para cada elemento del menú que tengan una; si se usa el
mismo nemónico varias veces, sólo la primera asignación trabaja. Generalmente, se usa la primera
letra de la opción. Si varios elementos del menú inician con la misma letra, la convención es escoger
la siguiente letra más prominente en el nombre.
Un acelerador es similar a un nemónico. Este es una combinación de teclas que cause que un elemento del menú sea escogido si está o no visible. Por ejemplo, varios programas permiten presionar
CTRL+P para imprimir desde cualquier lugar en el programa. Solo elementos menú hoja—
menús que no despliegan otros menús—pueden tener aceleradores. Por ejemplo, para asociar el
acelerador CTRL+A para la opción del menú “Marcar caja A”, se deberá poner en el constructor
de JFrameMenu2 del código 14 lo siguiente:
radio1.setAccelerator(
KeyStroke.getKeyStroke(KeyEvent.VK_A, Event.CTRL_MASK));
Actividad 2. Crear una aplicación para una empresa de eventos sociales la cual usa una barra
de menús con opciones múltples, y que usa varios JPanel separados con diferentes manejadores de
diseño para organizar los componentes.
33
Descargar