Você está na página 1de 65

Tema 5: Desarrollo de aplicaciones grficas

1.- Introduccin
2.- Ventanas: la clase Frame
3.- Componentes Bsicos
4.- Eventos de teclado y de ratn
5.- Estilos
6.- Dibujando
7.- Applets
8.- Dilogos y mensajes

Apndice A: Un poquito de Swing

1.- Introduccin
1.1 AWT y Swing
1.2 Un poco de filosofa
1.3 La jerarqua Component

1.1 AWT y Swing


Una de las razones del xito de Java es la posibilidad desde las primeras versiones, de una
gran cantidad de paquetes de clases destinadas al diseo de interfaces grficas. En otros
lenguajes (C, C++, etc.), las libreras de componentes grficos dependan del fabricante del
compilador particular que se decidiera utilizar. Esto favoreca la aparicin de dialectos del
lenguaje y la falta de uniformidad en el modelo propuesto.
La variedad de clases grficas y sus inmensas posibilidades de diseo hacer que un buen
programador en Java no sea slo aquel que conoce los aspectos bsicos del lenguaje y su
filosofa; es necesario tambin un conocimiento detallado de las clases del API (application
program interface) de Java y sus posibilidades.

Se pueden distinguir, principalmente, 2 grupos de clases destinadas al diseo de interfaces


grficos en Java:
AWT
Swing
La primera (Abstract Window Toolkit) es la que vamos a estudiar en este curso. El
conjunto de clases Swing naci a partir de AWT, simplificando los aspectos ms engorrosos
de AWT, dando mayor flexibilidad al programador para disear sus propios componentes
grficos (gracias all uso de beans) e incorporando numerosos componentes nuevos.
La pregunta que surge al leer esto es:
Si Swing es ms sencillo, ms flexible y ms potente que AWT,
por qu no limitarse a estudiar las clases de Swing?

La razn principal es que, a pesar de ser Swing ms fcil de manejar est basado en
conceptos ms complejos, difciles de entender si primero no se conoce AWT; Swing
contiene demasiado de AWT como para, simplemente, ignorarlo. La mayora de los autores
piensa que es mejor seguir al estudiar el lenguaje la evolucin que han seguido sus
diseadores. Por eso nos limitaremos aqu al estudio de AWT. Si se comprenden los
conceptos de este tema pasar posteriormente a Swing no supondr ningn problema. Otro
buena razn es que al ser AWT ms antiguo, los applets de internet escritos en AWT
funcionan en muchos ms exploradores que los escritos con Swing. Por tanto usando AWT
nos aseguramos una mayor compatibilidad.

Observacin: Por cada componente en AWT, el correspondiente componente en Swing


suele tener el mismo nombre pero precedido de una letra J. Por ejemplo, los botones se
representan en AWT mediante objetos de la clase Button y en Swing mediante objetos de la
clase JButton, las ventanas mediante las clases Frame y JFrame, y as sucesivamente.

1.2 Un poco de filosofa


El concepto bsico de la programacin grfica es el componente. Un componente es
cualquier cosa que tenga un tamao una posicin, pueda pintarse en pantalla y pueda recibir
eventos (es decir, pueda recibir acciones por parte del usuario). Un ejemplo tpico es un
botn; el evento ms normal que puede recibir es que el usuario de la aplicacin pulse el
botn. Podemos resumir los conceptos bsicos de la programacin grfica con AWT:
Todos los componentes son o bien contenedores (como Frame) o bien componentes
bsicos (como Button).
Los componentes bsicos siempre deben formar parte de un contenedor para ser visibles.

Los contenedores a su vez se pueden insertar en otros contenedores.


La posicin de un componente en un contenedor depende del tamao del contenedor y de
su estilo (Layout).
Todo componente incluye un atributo de tipo Graphicsque se encarga de dibujarlo
cuando hace falta. Si queremos dibujar en el componente tendremos que pedirle que nos
"deje" su objeto de tipoGraphics.
Si queremos que un componente haga algo cuando le ocurra un evento determinado
debemos pasarle un objeto tipo Listener al que l avisar llegado el momento.
Las idea clave de esta forma de proceder es la llamada delegacin de eventos. En una
aplicacin grfica La funcin main se encargar de crear la ventana principal, donde se
dispondrn los componentes y se indicar a cada componente a qu clase debe avisar
cuando le suceda un evento. A partir de este momento ser el propio lenguaje el que se
encargar de avisar a las clases adecuadas de la existencia de un evento como respuesta a
las acciones del usuario. Esto significa que se pierde el concepto de ejecucin secuencial
que hemos visto en los programas con entrada/salida de texto.

1.3 La jerarqua Component


La clase Component es una clase abstracta de la que derivan todos los componentes visuales
AWT. Tiene ms de 100 mtodos de los que vamos a mencionar slo los ms habituales:

Clase Component

Mtodo
String getName()

Descripcin
Devuelve el nombre del componente

void setName(String)

Para fijar el nombre del componente

Dimension getSize()

Devuelve el tamao del componente

void setSize(int ancho, int


alto)

Para modificar el tamao del componente

void setSize(Dimension)

Anlogo al anterior

Color getBackground

Devuelve el color de fondo del componente

void setBackground(Color)

Fija el color de fondo del componente

Color getForeground

Devuelve el color de primer plano del componente

void setForeground(Color)

Fija el color de primer plano del componente

Font2 getFont()

Devuelve el tipo de letra asociado al componente

void setFont(Font)

Fija el tipo de letra del componente

Boolean getVisible()

Indica si el componente es visible

void setVisible(Boolean)

Muestra/oculta el componente (til para ventanas)

Boolean getEnabled()

Indica si el componente est activo

void setEnabled(Boolean)

Activa/desactiva el componente (til para botones y opciones de men)

Graphics getGraphics()

Devuelve el objeto tipo Graphics que puede dibujar en el componente

repaint()

Llamaremos a este mtodo para pedirle al componente que se redibuje

repaint(int x, int y, int width, Llamaremos a este mtodo para pedirle al componente que redibuje el
int height)
rectngulo indicado
void Paint(Graphics g)

Redefiniremos este mtodo (usando herencia) cuando queramos dibujar


algo en el componente

void Update(Graphics g)

Mtodo que por defecto borra el componente y llama a paint() cuando


hay que repintar un componente. Se utiliza sobre todo en animaciones

Point3 getLocation()

Indica la posicin de la esquina superior izquierda del componente en su


contenedor

void setLocation(int x, int y)

Mueve el componente a la posicin indicada

void setLocation(Point p)

Mueve el componente a la posicin indicada

Container getParent()

Indica a qu contenedor pertenece el componente

Algunas observaciones sobre estos mtodos:


1. La clase Dimension de AWT sirve para almacenar el ancho y el alto de un
componente. Sus mtodos ms importantes son double getWidth(), double
getHeight() y sus correspondientes set.
2. La clase Font de AWT representa los tipos de letra. Es una clase compleja que no
vamos a ver en profundidad. La forma ms habitual de uso es como en este ejemplo:
// Arial de 12 pts en negrita
Font fuenteNegrita = new Font("Arial",Font.BOLD,12);

Las constantes de formato son: Font.PLAIN, Font.BOLD y Font.ITALIC.


3. La clase Point de AWT se utiliza para representar las coordenadas de un punto (x,y).
Tiene una constructora Point(x,y) y mtodos tales como int getX(), int getY(), void
setX(int x), void setY(int y) y void move(int x, int y).
El siguiente diagrama muestra esquemticamente las clases derivadas de Component:

Aunque no vamos a estudiarlas todas, conviene saber para qu sirve cada una de ellas, y
referirnos a la ayuda de Java cuando sea necesario:
Componentes
Bsicos
Clase

Descripcin

Button

Botones con un texto (Ej: Aceptar)

Canvas

Rectngulo para dibujar

Choice

Lista desplegable (ej: lista de pases para elegir)

CheckBox

Casillas cuadradas para marcar (como en un test)

Label

Etiqueta: caracteres que se muestran en un contenedor

List

Lista, similar a Choice pero constantemente desplegada

Scrollbar

Barra de desplazamiento

TextField

Campo de edicin que puede utilizar el usuario para introducir datos

TextArea

Similar a TextField pero permite introducir texto que ocupe varias lneas

Contenedore
s

Clase

Descripcin

Panel

Contenedor bsico que necesita formar parte de una ventana (o pgina)

Applet

Panel preparado para formar parte de una pgina HTML

Window

Una ventana sin ttulo ni casillas para minimizar,cerrar,etc.

Frame

Una ventana normal, con ttulo

Dialog

Ventana que se muestra sobre la ventana actual (Ej.: la tpica ventana para preguntar
"Est seguro de ...." y dos botones de Aceptar y Cancelar)

FileDialog

Similar al anterior, pero especializado para la seleccin de ficheros (se suele utilizar en
las opciones de "Abrir" o "Grabar como" )

2.- Ventanas: la clase Frame


2.1 Abriendo las ventanas
2.2 Cerrando las ventanas
2.3 Ejemplo
2.4 Utilizacin de la herencia

2.1 Abriendo las ventanas


La clase Frame representa en AWT una ventana tal y como estamos acostumbrados a verlas
en un entorno grfico. Dado que el resto de los componentes formarn parte de una ventana,
parece lgico que comencemos por ella.
Aviso: No es posible explicar en un espacio limitado todas las caractersticas de un
componente visual complejo como Frame, o como el resto de los estudiados en este tema.
Por tanto nos limitaremos a los aspectos bsicos, pero avisando de que en la ayuda de Java
se pueden encontrar mtodos, constructoras, etc. no discutidos aqu.
Para crear e inicializar una ventana AWT (Frame) vamos a seguir los siguientes pasos:
Crear la variable tipo Frame
Para eso utilizaremos alguna de las constructoras de la clase, que son:

Frame(): Constructora sin parmetros; crea una ventana sin ttulo


Frame(String): Crea una ventana con el ttulo que se le indica Por ejemplo:
Frame ventana = new Frame("Ventana de prueba");

Tamao y posicin iniciales

El tamao se fija con el mtodo void setSize(int, int) y la posicin con setLocation(int,int).
Ambos pertenecen a la clase Component. Ejemplo:
ventana.setSize(300, 100);
ventana.setLocation(100,50);

Hay que observar que el tamao y la posicin dependen de la configuracin de la pantalla.


Para conocer el tamao en pixels de la pantalla podemos utilizar el
mtodoToolkit.getDefaultToolkit().getScreenSize();, que devuelve un objeto de
tipo Dimension. Por ejemplo, para que la ventana aparezca centrada y ocupe un tercio de la
pantalla tanto en ancho como en alto podemos escribir:
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
// calculamos el tamao de la ventana a partir del ancho de la pantalla
int ancho=d.width/3;
int alto=d.height/3;
ventana.setSize(ancho, alto);
ventana.setLocation(d.width/2-ancho/2,d.height/2-alto/2);

Otras inicializaciones (opcional)


Tambin podemos fijar los colores, el tipo de letra, el ttulo (con void setTitle(String)) o el
icono que mostrar la ventana al minimizarse (con void setImage(Image)). Por ejemplo:
ventana.setBackground(new Color(20,140,10));
ventana.setForeground(Color.blue);
Font fuente = new Font("Arial", Font.PLAIN, 20);
ventana.setFont(fuente);
ventana.setTitle("Ejemplo de ventana ");

Fijar el estilo (opcional)


Hablaremos de los "estilos" ms adelante. De momento baste con decir que el
mtodo setLayout(Layout) determina el estilo de la ventana, es decir cmo se distribuyen
los componentes en la ventana. Por ejemplo:
FlowLayout estilo = new FlowLayout();
ventana.setLayout(estilo);

har que los componentes se siten uno al lado del otro, de izquierda a derecha y de arriba a
abajo.
Observacin: Todos los estilos (como FlowLayout) son subclases de la clase Layout y
por eso pueden ser utilizados como argumentos del mtodo setLayout. Es un ejemplo de
polimorfismo.
Incorporar los componentes
En este paso se aaden los componentes que se desee incluir en la ventana. Para eso se
utiliza el mtodo void add(Component) heredado de la clase Container. Por ejemplo:
Label etiq = new Label("Te estoy mirando...");
ventana.add(etiq);

Observacin: Otro ejemplo de polimorfismo: etiq es de tipo Label, pero Label hereda
de Component y por eso etiq puede ser argumento del mtodo add, cuyo argumento est
declarado de tipo Component.

Aviso: Es importante que no olvidemos incorporar los componentes bsicos a un


contenedor; en otro caso no podrn ser visibles.
Mostrar la ventana
Esto se hace con el mtodo setVisible heredado de Component.
ventana.setVisible(true);

Aviso: Un error habitual es olvidar este paso con lo que la ventana no se mostrar

Observacin: La utilizacin de setVisible permite "cambiar" de una ventana a otra,


haciendo visible la que estaba oculta y viceversa.

Poniendo todo el cdigo anterior junto obtenemos la siguiente ventana:

2.2 Cerrando las ventanas


Una ventana puede recibir los siguientes tipos de eventos:

WINDOW_OPENED
WINDOW_CLOSING
WINDOW_CLOSED
WINDOW_ICONIFIED
WINDOW_DEICONIFIED
WINDOW_ACTIVATED
WINDOW_DEACTIVATED
WINDOW_GAINED_FOCUS

WINDOW_LOST_FOCUS
WINDOW_STATE_CHANGED

Para tener acceso a ellos debemos:


Escribir una clase para atenderlos. Esta clase debe heredar de WindowAdapter o bien
implementar el interfaz WindowListener
Pasarle a la ventana un objeto de ese tipo a la ventana mediante el
mtodo addWindowListener. La ventana llamar al mtodo adecuado correspondiente a
cada evento.
Los mtodos son:

void windowActivated(WindowEvent e)
void windowClosed(WindowEvent e)
void windowClosing(WindowEvent e)
void windowDeactivated(WindowEvent e)
void windowDeiconified(WindowEvent e)
void windowIconified(WindowEvent e)
void windowOpened(WindowEvent e)

De todos ellos el que nos interesa ahora es windowClosing que se utiliza cuando el usuario
trata de cerrar la ventana. Para que al pulsar se cierre realmente tendremos que incluir una
llamada a System.exit(0), que fuerza el fin de la aplicacin. La clase puede ser por ejemplo:
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

Y el cdigo para que la ventana utilice este mtodo:


ParaAcabar acabar = new ParaAcabar();
ventana.addWindowListener(acabar);

Observacin: Si en lugar de heredar de WindowAdapter hubiramos implementado su


interfaz correspondiente (WindowListener) habramos tenido que incluir todos los mtodos
anteriores en la clase, aunque slo estemos interesados en uno de ellos.

Observacin: En swing el componente correspondiente se llama JFrame, y permite


indicar que se quiere salir de la aplicacin al cerrar la ventana sin necesidad de escribir un
objeto escucha, simplemente con:

JFrame ventana = new ...


....
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

2.3 Ejemplo
El siguiente programa rene todos los conceptos anteriores:
Principal.java
import java.awt.*;
import java.awt.event.*;
public class Principal {
public static void main(String[] args) {
// objeto de tipo ventana
Frame ventana = new Frame("Ventana de prueba");
// ventana cuadrada centrada en la pantalla y
// ocupando un tercio de la pantalla
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
// calculamos el tamao de la ventana a partir del ancho de la pantalla
int ancho=d.width/3;
int alto=d.height/3;
ventana.setSize(ancho, alto);
ventana.setLocation(d.width/2-ancho/2,d.height/2-alto/2);
// colores, ttulo y fuente
ventana.setBackground(new Color(20,140,10));
ventana.setForeground(Color.blue);
Font fuente = new Font("Arial", Font.PLAIN, 20);
ventana.setFont(fuente);
ventana.setTitle("Ejemplo de ventana ");
// estilo
FlowLayout estilo = new FlowLayout();
ventana.setLayout(estilo);
// componentes
Label etiq = new Label("Te estoy mirando...");
ventana.add(etiq);
// aadimos el "listener" para cerrar la ventana
ParaAcabar acabar = new ParaAcabar();
ventana.addWindowListener(acabar);
// hacemos la ventana visible
ventana.setVisible(true);
}
}
// clase escucha que se ejecuta al tratar de cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0); // abandonar la aplicacin

}
}

Es interesante observar que la clase para cerrar la ventana se encuentra, por comodidad, en
el mismo fichero que la clase principal. Esto es posible porque esta clase no es pblica.
Observacin: En cada fichero .java puede haber una nica clase pblica, pero tambin se
permite incluir otras clases -no pblicas- que sirvan de clases auxiliares de la clase pblica.

2.4 Utilizacin de la herencia


Es muy normal separar el cdigo asociado a la ventana del main, haciendo una clase aparte
que se encargue de la gestin de la ventana. Entonces la aplicacin queda compuesta de dos
clases: la clase Ventana, y la clasePrincipal que se limita a crear la ventana y a hacerla
visible. La configuracin de la ventana (colores, tamao, posicin, componentes, escuchas,
etc.) se har entonces en la constructora de la clase Ventana, que se definir hija de la
clase Frame:
Ventana.java

import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
public Ventana() {
// ventana cuadrada centrada en la pantalla y
// ocupando un tercio de la pantalla
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
// calculamos el tamao de la ventana a partir del ancho de la pantalla
int ancho=d.width/3;
int alto=d.height/3;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
// colores, ttulo y fuente
setBackground(new Color(20,140,10));
setForeground(Color.blue);
Font fuente = new Font("Arial", Font.PLAIN, 20);
setFont(fuente);
setTitle("Ejemplo de ventana ");
// estilo
FlowLayout estilo = new FlowLayout();
setLayout(estilo);
// componentes
Label etiq = new Label("Te estoy mirando...");
add(etiq);
// aadimos el "listener" para cerrar la ventana
ParaAcabar acabar = new ParaAcabar();

addWindowListener(acabar);
}
}
// clase escucha que se ejecuta al tratar de cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0); // abandonar la aplicacin
}
}

De esta forma la clase ventana tiene todos los mtodos de la clase Frame ms todos los que
nosotros aadamos posteriormente. La clase principal queda simplemente:
Principal.java
public class Principal {
public static void main(String[] args) {
// objeto de tipo ventana
Ventana ventana = new Ventana();
// hacemos la ventana visible
ventana.setVisible(true);
}
}

y en el resto del captulo a menudo la omitiremos para evitar repetir el cdigo, que es
independiente de la ventana.

3.- Componentes Bsicos


3.1 Etiquetas: la clase Label
3.2 Botones: la clase Button
3.3 Entrada de datos: la clase TextField
3.4 reas de texto: la clase TextArea
3.5 Marcas casillas: la clase Checkbox

3.1 Etiquetas: la clase Label


La clase Label(etiqueta) se utiliza para mostrar Strings en un componente.
Constructoras
Tiene 3 constructoras:

Label(): La constructora por defecto, crea una etiqueta con un String vaco.

Label(String etiq): Etiq es el String a mostrar.


Label(String etiq, int alineamiento): Permite indicar si la etiqueta se mostrar en el
espacio reservado para ella en el component alineada a la izquierda
(constante Label.LEFT), a la derecha (Label.RIGHT) o centrada (Label.CENTER).

Mtodos
Aparte de los mtodos heredados de Object y Component, esta clase tiene dos mtodos
importantes:

setText(String etiq): Para modificar el contenido de la etiqueta.


String getText(): Devuelve el contenido actual de la etiqueta.

3.2 Botones: la clase Button


Este componente es bsico; sobre el suelen recaer las acciones del usuario y a menudo en
sus escuchas asociadas se realiza la parte ms complicada del programa. La filosofa que se
sigue es vlida para otros componentes que no discutimos aqu, como los
mens. Constructoras
Tiene 2 constructoras:

Button(): Botn con un mensaje vaco.


Button(String etiq): Etiq es el String a mostrar como mensaje.

Mtodos
Algunos de los mtodos ms importantes, adems de los heredados de Component, son:

void setLabel(String label) : Cambia la etiqueta del botn.


String getLabel() : Devuelve la etiqueta actual.
void setActionCommand(String command): Asocia un String al botn. Este String no
se mostrar por pantalla, sino que se utilizar como identificador del botn.
void addActionListener(ActionListener l): Para aadir una escucha que pueda
reaccionar cuando se pulsa el botn. Se explica en el apartado siguiente.

Vamos a ver un primer ejemplo. En este ejemplo se separa la aplicacin en dos clases
independientes: la clase con el main y la clase con la ventana:
Ventana.java
package ventanas;
import java.awt.*;
import java.awt.event.*;

public class Ventana extends Frame {


Button botn;
Label etiq;
// constructora
public Ventana() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Ejemplo de ventana con boton (v.1) ");
setLayout(new FlowLayout());
setSize(300, 100); setLocation(100,50);
// le damos un poco de color a la ventana
setBackground(Color.yellow);
// una etiqueta
etiq = new Label("Un botn:");
add(etiq);
// creamos el botn
botn = new Button("Plsame");
botn.setBackground(Color.blue);
botn.setForeground(Color.white);
// lo incorporamos a la ventana
// importante: si no se hace esto no sera visible
add(botn);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
}

System.exit(0); }

En este ejemplo aparece la ventana pero al pulsar el botn todava no hace nada. En el
siguiente apartado veremos como hacer que el botn "reaccione" cuando es pulsado.
Eventos
La idea es que no ser el propio botn sino un objeto escucha el que ser informado por
Java para que acte cuando el botn sea pulsado. Para lograr esto hay que:
1. Escribir una clase adecuada a la que pertenecer el objeto escucha. Esta clase debe,
en el caso de los botones, implementar el interfaz java.awt.event.ActionListener.
2. Declarar un objeto del tipo anterior (normalmente en la constructora de la ventana, a
la vez que se crea el botn).
3. Asociar el objeto de tipo escucha con el botn o, dicho con la terminologa habitual
de Java, registrar el objeto como escucha del botn. Esto se hace utilizando el
mtodo void addActionListener(ActionListener l).
El interfaz ActionListener tiene un slo mtodo: void actionPerformed(ActionEvent e), al
que se invocar cuando ocurra un evento sobre el botn (normalmente que ha sido pulsado).

El objetoActionEvent nos servir para saber ms informacin acerca del evento, y


normalmente se us cuando el mismo objeto de tipo ActionListener se utiliza de escucha para
ms de un botn, ya que nos permite saber cul de los botones ha sido pulsado. En
particular contiene 2 mtodos que pueden ser tiles.

String getActionCommand() .
Object getSource(): Fuente del evento (objeto de tipo Button).

El siguiente ejemplo hace que el botn, al ser pulsado escriba por pantalla el mensaje
"Gracias".
Ventana.java

package ventanas;
import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
Button botn;
Label etiq;
// constructora
public Ventana() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Ejemplo de ventana con boton (v.2) ");
setLayout(new FlowLayout());
setSize(300, 100); setLocation(100,50);
// le damos un poco de color a la ventana
setBackground(Color.yellow);
// una etiqueta
etiq = new Label("Un botn:");
add(etiq);
// creamos el botn
botn = new Button("Plsame");
botn.setBackground(Color.blue);
botn.setForeground(Color.white);
// lo incorporamos a la ventana
// importante: si no se hace esto no sera visible
add(botn);
// preparamos la escucha del boton
Escucha e = new Escucha();
// la registramos
botn.addActionListener(e);
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
}

}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
// escucha del boton
class Escucha implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("Gracias");
}
}

Ejercicio: Hacer que el botn escriba al hacer click el nmero de veces que ha sido pulsado
desde que ha comenzado la aplicacin (solucin en el siguiente apartado).
Interaccin con otros componentes grficos
Supongamos que pretendemos que el botn cambie de color de fondo cada vez que se le
pulse. Para ello podemos utilizar el mtodo setBackground y generar un color aleatorio
utilizando el mtodoMath.random(). Un primer intento consiste en modificar la
clase Escucha de la siguiente forma:
// escucha del boton
class Escucha implements ActionListener {
public void actionPerformed(ActionEvent e) {
// generamos un color aleatorio
Color c = new Color((int)(Math.random()*256),(int)(Math.random()*256),
(int)(Math.random()*256));
// cambiamos el color del boton
boton.setBackground(c);
}
}

Pero al compilar el cdigo anterior obtenemos un error:


C:\JCreator LE\MyProjects\gracias\ventanas\Ventana.java:67: cannot resolve symbol
symbol : variable boton
location: class ventanas.Escucha
boton.setBackground(c);
^

La razn es que la variable boton no es visible dentro de la clase Escucha. Afortunadamente


podemos obtener el botn a partir de la variable ActionEvent e de la siguiente forma:
// escucha del boton
class Escucha implements ActionListener {
public void actionPerformed(ActionEvent e) {
Button boton = (Button) e.getSource();
// generamos un color aleatorio
Color c = new Color((int)(Math.random()*256),(int)(Math.random()*256),
(int)(Math.random()*256));
// cambiamos el color del boton
boton.setBackground(c);

}
}

Esta solucin no se puede aplicar si queremos interactuar con otro componente distinto del
botn.
Ejemplo: Supongamos que queremos que al pulsar el botn se muestre en la etiqueta el
nmero de veces que se ha pulsado el botn desde que comenz la aplicacin.
En este caso no nos vale de nada la variable ActionEvent e; la etiqueta est definida en la
clase ventana y debemos ''obtenerla'' de otra forma. Vamos a ver dos posibilidades:
1.
Definir un atributo en la clase escucha que contendr una referencia al componente
externo deseado.
Este atributo se inicializar mediante la constructora.

2.
En nuestro caso:
3. Ventana.java

4.
5. package ventanas;
6.
7. import java.awt.*;
8.
9. import java.awt.*;
10. import java.awt.event.*;
11.
12. public class Ventana extends Frame {
13.
14.
// constructora
15.
public Ventana() {
16.
17.
// titulo, estilo, tamao y posicin iniciales
18.
setTitle("Ejemplo de ventana con boton (v.3) ");
19.
setLayout(new FlowLayout());
20.
setSize(300, 100);
21.
setLocation(100,50);
22.
23.
// le damos un poco de color a la ventana
24.
setBackground(Color.yellow);
25.
26.
// una etiqueta
27.
Label etiq = new Label("An no has pulsado");
28.
add(etiq);
29.
30.
// creamos el boton
31.
Button boton = new Button("Plsame");
32.
boton.setBackground(Color.blue);
33.
boton.setForeground(Color.white);
34.
35.
// incorporamos el boton al frame
36.
// importante: si no se hace esto no sera visible
37.
add(boton);

38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.

// preparamos la escucha del boton


Escucha e = new Escucha(etiq);
// la registramos
boton.addActionListener(e);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
// la mostramos
setVisible(true);
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
// escucha del boton
class Escucha implements ActionListener {
int i; // para contar las veces que se ha pulsado
Label etiqueta; // etiqueta que se modificar
public Escucha(Label etiqueta) {
this.etiqueta = etiqueta;
i=0;
}
public void actionPerformed(ActionEvent e) {
i++;
etiqueta.setText("Has pulsado "+i+" veces");
}
}

80. Ahora s que el programa funcionar correctamente:

82.
83.

81.

Escribir la clase escucha dentro de la clase Ventana.

84.
Java permite escribir una clase auxiliar dentro de la clase con la que ''colabora''. As

podemos definir la clase escucha como una subclase privada de la clase Ventana, que
al ser miembro de la clase tiene acceso a los atributos:
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.

package ventanas;
import java.awt.*;
import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
private int contador;
private Label etiq;
private Button botn;
// constructora
public Ventana() {
contador = 0;
// titulo, estilo, tamao y posicin iniciales
setTitle("Ejemplo de ventana con boton (v.3) ");
setLayout(new FlowLayout());
setSize(300, 100); setLocation(100,50);
// le damos un poco de color a la ventana
setBackground(Color.yellow);
// una etiqueta
etiq = new Label("An no has pulsado");
add(etiq);
// creamos el boton
botn = new Button("Plsame");
botn.setBackground(Color.blue);
botn.setForeground(Color.white);
// incorporamos el boton al frame
// importante: si no se hace esto no sera visible
add(botn);
// preparamos la escucha del boton
Escucha e = new Escucha();
// la registramos
botn.addActionListener(e);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
}
// escucha del botn
private class Escucha implements ActionListener {
public void actionPerformed(ActionEvent e) {
contador++;
etiq.setText("Has pulsado "+contador+" veces");
}
}
} // fin de la clase Ventana
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {

142.
public void windowClosing(WindowEvent e) {System.exit(0);}
143. }

Esta solucin es ms sencilla; nos ahorramos la constructora, la copia de la referencia para


acceder a los objetos, etc. A cambio es menos elegante y ms limitada; por ejemplo no nos
permite definir la clase escucha en un fichero aparte, para poder compartirla por varias
aplicaciones.
Utilizando la misma escucha para varios botones
Supongamos que queremos tener una etiqueta que haga de contador comenzando en 0.
Incluiremos dos botones, uno para incrementar el contador y otro para decrementarlo. A la
hora de establecer las escuchas hay dos posibilidades:
1. Escribir dos clases escucha, una para el botn de incrementar y otra para el de
decrementar.
2. Utilizar la misma escucha para ambos.
El segundo mtodo es, en este caso, ms cmodo, pero tenemos que ser capaces de
distinguir dentro del mtodo actionPerformed cul de los dos botones ha sido pulsado, para
as incrementar o decrementar el contador. Para esto podemos utilizar el
mtodo setActionCommand de la clase Button y getActionCommand de ActionEvent, tal y
como muestra el programa siguiente:
Ventana.java

package ventanas;
import java.awt.*;
import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
// constructora
public Ventana() {
// titulo, estilo, tamao y posicin iniciales
setTitle("contadores ");
setLayout(new FlowLayout());
setSize(200, 100);
setLocation(100,50);
// le damos un poco de color a la ventana
setBackground(Color.yellow);
// las etiquetas
Font fuente = new Font("Arial", Font.PLAIN, 20);
Label etiq = new Label("Contador: ");
etiq.setFont(fuente);
add(etiq);
Label etiq2 = new Label("0");

etiq2.setFont(fuente);
add(etiq2);
// preparamos la escucha del boton
Escucha e = new Escucha(etiq2);
// creamos los botones
Button botonInc = new Button("Incremento");
botonInc.setActionCommand("inc");
botonInc.setBackground(Color.blue);
botonInc.setForeground(Color.white);
add(botonInc);
botonInc.addActionListener(e);
Button botonDec = new Button("Decremento");
botonDec.setActionCommand("dec");
botonDec.setBackground(Color.red);
botonDec.setForeground(Color.white);
add(botonDec);
botonDec.addActionListener(e);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
// escucha del boton
class Escucha implements ActionListener {
int contador; // para contar las veces que se ha pulsado
Label etiqueta; // etiqueta que se modificar
public Escucha(Label etiqueta) {
this.etiqueta = etiqueta;
contador=0;
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("inc"))
contador++;
else
contador--;
etiqueta.setText(" "+contador+" ");
}
}

El programa tendr el siguiente aspecto:

3.3 Entrada de datos: la clase TextField


Este componente se utiliza comnmente para leer datos de teclado.
Constructoras
Para TextField:

TextField(): Constructora por defecto conteniendo la cadena vaca y con 0 columnas.


TextField(int columnas): Contenido vaco pero longitud prefijada inicial.
TextField(String texto) Campo de texto con un valor inicial.
TextField(String texto, int columnas): Las dos anteriores combinadas.

Mtodos
La clase TextField coincide con las clases anteriores en la definicin de los
mtodos setText(String cadena) y String getText(). Algunos otros mtodos de inters:

setEchoChar(Char c): Indica el carcter que aparece cuando se introduce un valor y


se usa para introducir palabras clave. setEchoChar(0) hace que el carcter que
aparece sea el carcter pulsado.
setEditable(boolean): Si se pone a false no se podr escribir sobre el campo de
edicin.
int getSelectionStart(), int getSelectionEnd(): Para saber el trozo de texto que ha sido
seleccionado por el usuario. Muy til para las acciones de "Copiar", "Cortar" y
"Pegar".
void setSelectionStart(int inicio), void setSelectionEnd(int fin): Para marcar una
porcin de texto. En realidad setSelectionEnd(int fin) indica una posicin ms all de
la ltima a marcar. Por ejemplo, para marcar los caracteres 2,3 y 4 (tercer, cuarto y
quinto carcter) se utilizara:
texto.setSelectionStart(2);
texto.setSelectionEnd(5);

Eventos
En cuanto a los eventos, la diferencia principal con la clase Button es que el
mtodo ActionEvent de la clase escucha se utiliza cuando se pulsa Enter. Tambin se puede
controlar cual es la tecla pulsada, como veremos al hablar de los eventos de teclado, pero
estos eventos no son especficos de la clase TextField sino comunes a todos los Component.

Ejemplo: Clase para representar una ventana de entrada a un sistema, con login y
password:
PalabraClave.java

package claves;
import java.awt.*;
import java.awt.event.*;
public class PalabraClave extends Frame {
private Label etiq,etiq2,etiq3;
private Button aceptar;
private TextField login;
private TextField pass;
public PalabraClave() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Entrada al Sistema");
setLayout(new FlowLayout());
// ventana centrada
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int ancho=300, alto=200;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
// tipo de letra
Font fuente = new Font("Arial", Font.PLAIN, 18);
setFont(fuente);
// un poco de color
setBackground(Color.cyan);
// preparamos la entrada de datos
etiq = new Label("Login:
");
add(etiq);
login = new TextField(8);
add(login);
etiq2 = new Label("Password:");
etiq2.setFont(fuente);
add(etiq2);
pass = new TextField(10);
pass.setEchoChar('*');
add(pass);
aceptar = new Button("Aceptar");
add(aceptar);
etiq3 = new Label("Pulsa Aceptar para Continuar");
add(etiq3);

// preparamos las escuchas


EscuchaAceptar e = new EscuchaAceptar();
aceptar.addActionListener(e);
pass.addActionListener(e);
// esta vale slo para el campo de login
EscuchaSiguiente pasaAlSiguiente = new EscuchaSiguiente();
login.addActionListener(pasaAlSiguiente);
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
}
// escuchas como subclases privadas ///////////////////////
// escucha del boton Aceptar
private class EscuchaAceptar implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (vlidos(login.getText(), pass.getText()))
etiq3.setText("Datos vlidos");
else
etiq3.setText("Datos no vlidos");
}
private boolean vlidos(String login, String pass) {
// aqu se comprueba
return login.equals("Bertoldo") && pass.equals("nolose");
}
}
// clase escucha para el primer campo de edicin; le pasa el foco
// al siguiente
private class EscuchaSiguiente implements ActionListener {
public void actionPerformed(ActionEvent e) {
// componente sobre el que ha ocurrido el evento
Component c = (Component) e.getSource();
// indicarle que pase el foco al siguiente elemento
c.transferFocus();
}
}
////////////////////// fin escuchas //////////////////////////////
} // Ventana
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {System.exit(0);}
}

La ejecucin del programa tendr el siguiente aspecto:

3.4 reas de texto: la clase TextArea


Es similar a TextField con la diferencia de que al presentarse en pantalla permite introducir
cdigo que ocupa ms de una lnea.
Constructoras

TextArea(): rea de texto con una cadena vaca. Tamao de alrededor de 55 filas por
15 columnas
TextArea(int filas, int columnas): Fija el nmero de filas y columnas. Si el nmero
excede el tamao del TextArea se incluyen automticamente las barras de
desplazamiento.
TextArea(String texto): Texto inicial.
TextArea(String texto, int filas, int columnas): Texto inicial con filas y columnas
prefijadas.
TextArea(String texto, int filas, int columnas, int barras): Aade al anterior la
posibilidad de controlar la existencia de barras de desplazamiento. Los posibles
valores de barras son:
o SCROLLBARS_BOTH
o SCROLLBARS_HORIZONTAL_ONLY
o SCROLLBARS_NONE
o SCROLLBARS_VERTICAL_ONLY

Mtodos y Eventos
Los mtodos y eventos son como los de TextField con algunos mtodos aadidos, entre los
que podemos destacar:

void replaceRange(String str, int start, int end) : Cambia el texto entre las
posiciones start y end por el texto str.
insert(String str, int pos): Inserta el texto en la posicin indicada.
append(String str): Aade el texto indicado al final.

3.5 Marcar casillas: la clase Checkbox

La clase Checkbox nos permite mostrar texto acompaado de casillas con dos estados:
marcada o no marcada. Varios Checkbox pueden agruparse de forma que nos aseguremos
de que slo una casilla est marcada en cada momento. Vamos a ver las dos posibilidades
en dos ejemplos separados: Casillas no agrupadas
En este caso basta con declarar y aadir los Checkbox independientemente. La etiqueta
asociada a la casilla se puede fijar en la constructora o bien posteriormente con el
mtodo setLabel(String). El estado (activada o no) se puede modificar y consultar con los
mtodos setState(boolean) y getState(), respectivamente. El siguiente ejemplo muestra el
uso de este componente:
Ventana.java
import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
// la ventana contiene 4 casillas
private Checkbox casilla1,casilla2,casilla3,casilla4;
// dos etiquetas
Label etiq1, etiq2;
// y un botn
private Button aceptar;
public Ventana() {
// objeto de tipo ventana
setTitle("Prueba de Checkbox");
setSize(380, 150);
setLayout(new FlowLayout());
Font fuenteNegrita = new Font("Arial",Font.BOLD,16);
setFont(fuenteNegrita) ;
etiq1 = new Label("Marque sus aficiones favoritas y pulse Aceptar");
add(etiq1);
// una forma de construir una casilla
casilla1 = new Checkbox();
casilla1.setLabel("Deportes");
// otra forma
casilla2 = new Checkbox("Lectura");
casilla3 = new Checkbox("Viajes");
casilla4 = new Checkbox("Cine");
// hacemos que la casilla Cine aparezca marcada
casilla4.setState(true);
add(casilla1); add(casilla2); add(casilla3); add(casilla4);
aceptar = new Button("Aceptar");
add(aceptar);
// escucha del botn
aceptar.addActionListener(new EscuchaBotn());
// etiqueta donde se mostrar el resultado
etiq2 = new Label("");
// aadimos la escucha para cerrar la ventana

addWindowListener(new ParaAcabar());
}
//////////////////////////////////////////////////////
// escucha del boton
class EscuchaBotn implements ActionListener {
public void actionPerformed(ActionEvent e) {
String aficiones = "Ha elegido: ";
if (casilla1.getState()) aficiones += casilla1.getLabel()+"
if (casilla2.getState()) aficiones += casilla2.getLabel()+"
if (casilla3.getState()) aficiones += casilla3.getLabel()+"
if (casilla4.getState()) aficiones += casilla4.getLabel()+"

";
";
";
";

// aadimos a la ventana un label con los objetos elegidos


add(new Label(aficiones));
}
}
}
// clase escucha que se ejecuta al tratar de cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0); // abandonar la aplicacin
}
}

El resultado es:

Casillas agrupadas
Similar al anterior, pero agrupando las casillas por medio de un objeto
tipo CheckboxGroup, para lo que se usa una tercera constructora que permite indicar el
grupo al que pertenece la casilla, as como si est activa (cada grupo tendr como mximo
una casilla marcada). Los mtodos de CheckboxGroup Checkbox
getSelectedCheckbox() y void setSelectedCheckbox(Checkbox) sirven para obtener y
cambiar, respectivamente, el Checkbox seleccionado. Ejemplo:
Ventana.java
import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
// grupo de 3 casillas
private CheckboxGroup grupo;
private Checkbox c1,c2,c3;
// y una etiqueta
Label etiq1;

public Ventana() {
setTitle("Prueba de CheckboxGroup");
setSize(300, 80);
setBackground(Color.yellow);
setLayout(new FlowLayout());
Font fuenteNegrita = new Font("Arial",Font.BOLD,16);
setFont(fuenteNegrita) ;
etiq1 = new Label("Destino:");
add(etiq1);
// primero se construye el "agrupador"
grupo = new CheckboxGroup();
// ahora se crean las casillas indicando que estn en el grupo
c1 = new Checkbox("Madrid",grupo,false);
c2 = new Checkbox("Pars",grupo,false);
c3 = new Checkbox("Berln",grupo,true);
// aadir las casillas a la ventana; el grupo NO se aade
add(c1); add(c2); add(c3);
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
}
}
// clase escucha que se ejecuta al tratar de cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0); // abandonar la aplicacin
}
}

El resultado es:

4.- Eventos de teclado y de ratn


4.1 Eventos de teclado
4.2 Eventos de ratn

4.1 Eventos de teclado


Los eventos de teclado detectan la pulsacin de teclas. Cualquier componente puede
registrar una escucha de teclado, al igual que una escucha para el ratn. El componente que
recibe la entrada de teclado en cada momento es nico; se dice que ese componente "tiene

el foco". Un componente puede pedir el foco utilizando el mtodo requestFocus(). Para


detectar los eventos de teclado, un componente debe:
Escribir una clase que implemente el interfaz KeyListener.
Declarar un objeto de la clase anterior.
Registrarlo con addKeyListener(KeyListener escucha), un mtodo de la
clase Component.
El interfaz KeyListener dispone de los siguientes mtodos:

void keyPressed(KeyEvent e): Tecla pulsada.


void keyReleased(KeyEvent e): Se dej de pulsar la tecla.
void keyTyped(KeyEvent e): La combinacin de las dos anteriores.

Por su parte, el parmetro de tipo KeyEvent contiene los siguientes mtodos que nos ayudan
a identificar la tecla concreta:

char getKeyChar(): Devuelve el carcter asociado a la tecla, si es una tecla normal


(imprimible). Las teclas especiales devuelven la constante CHAR_UNDEFINED.
boolean isActionKey(): Devuelve true si la tecla es una tecla especial o false si es
imprimible.
int getKeyCode(): Devuelve una constante identificando a la tecla si es una tecla
especial. Algunas de estas constantes son:
VK_ACCEPT, VK_ALT, VK_ALT_GRAPH, VK_BACK_QUOTE,
VK_BACK_SLASH, VK_BACK_SPACE, VK_CANCEL, VK_CAPS_LOCK,
VK_CLEAR, VK_CLOSE_BRACKET, VK_CODE_INPUT, VK_COLON,
VK_COMMA, VK_COMPOSE, VK_CONTROL, VK_COPY, VK_CUT,
VK_DELETE, VK_DOWN, VK_END, VK_ENTER, VK_ESCAPE,
VK_EURO_SIGN, VK_F1, VK_F10, VK_F11, VK_F12, VK_F13, VK_F14,
VK_F15, VK_F16, VK_F17, VK_F18, VK_F19, VK_F2, VK_F20, VK_F21,
VK_F22, VK_F23, VK_F24, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8,
VK_F9, VK_FINAL, VK_FIND, VK_HELP, VK_HOME, VK_INSERT,
VK_LEFT, VK_NUM_LOCK, VK_NUMPAD0, VK_NUMPAD1,
VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5,
VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_O,
VK_PAGE_DOWN, VK_PAGE_UP, VK_PASTE, VK_PAUSE,
VK_PRINTSCREEN, VK_RIGHT, VK_SCROLL_LOCK, VK_SHIFT, VK_STOP,
VK_TAB, VK_UNDEFINED, VK_UNDO, VK_UP.

Ejemplo: Hacer que la posicin de una etiqueta cambie con las teclas de cursor. El
programa tambin avisar si se pulsa la tecla Bloq. Nm.
Teclas.java

import java.awt.*;
import java.awt.event.*;
public class Teclas extends Frame {
private Label etiq; // nico componente
public Teclas() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Teclas");
setLayout(new FlowLayout());
// ventana centrada
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int ancho=300, alto=200;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
// tipo de letra
Font fuente = new Font("Arial", Font.PLAIN, 18);
setFont(fuente);
// un poco de color
setBackground(Color.cyan);
// preparamos la entrada de datos
etiq = new Label("Pulsa 'S' para salir
add(etiq);

");

// escucha de teclado para la ventana;


// le pasamos como parmetro la etiqueta
EscuchaTeclas e = new EscuchaTeclas(etiq);
addKeyListener(e);
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
// si no hacemos esto el foco se lo queda la etiqueta!!!
requestFocus();
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
// escucha de teclaro
class EscuchaTeclas implements KeyListener {
private Label etiq;
public EscuchaTeclas(Label etiq) {
this.etiq = etiq;
}
public void keyPressed(KeyEvent e){
if (e.isActionKey()==false && e.getKeyChar() == 'S') {
System.exit(0);

} else {
// guardamos el cdigo de la tecla especial
int tecla = e.getKeyCode();
// la posicin actual de la etiqueta
Point pos = etiq.getLocation();
switch(tecla) {
case KeyEvent.VK_UP:
etiq.setLocation(pos.x,pos.y-1);
break;
case KeyEvent.VK_DOWN:
etiq.setLocation(pos.x,pos.y+1);
break;
case KeyEvent.VK_LEFT:
etiq.setLocation(pos.x-1,pos.y);
break;
case KeyEvent.VK_RIGHT:
etiq.setLocation(pos.x+1,pos.y);
break;
case KeyEvent.VK_NUM_LOCK:
etiq.setText("Bloque numrico");
break;
default:
}
}
}
// hay que incluir estos mtodos aunque no se necesiten
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {

4.2 Eventos de ratn


Existen dos interfaces para el control del ratn, cada uno correspondiendo a un tipo de
evento.
MouseListener
Sirve para detectar las pulsaciones del ratn y responde a los eventos del tipo MouseEvent.
El interfaz consta de 5 mtodos:

void mouseClicked(MouseEvent e): Se ha pulsado el ratn.


void mouseEntered(MouseEvent e): El ratn se ha situado sobre un componente
(aunque no se haya pulsado).
void mouseExited(MouseEvent e): El ratn abandona el componente sobre el que
estaba situado.
void mousePressed(MouseEvent e): Se ha pulsado un botn del ratn.
void mouseReleased(MouseEvent e): Se ha soltado un botn del ratn que estaba
pulsado.

La clase MouseEvent tiene entre otros mtodos:

int getX() : coordenada x del ratn.


int getY() : : coordenada y del ratn.
Point getPoint() : posicin del ratn.
int getClickCount() : Informa sobre el nmero de pulsaciones, para distinguir el
"doble-click".
int getButton() : Informa sobre el botn que ha cambiado de estado. Puede devolver
las constantes: BUTTON1, BUTTON2, BUTTON3.

Ejemplo: Vamos a mover un botn para que el usuario no pueda pulsarlo nunca:
CorreRaton.java

import java.awt.*;
import java.awt.event.*;
public class CorreRaton extends Frame {
public CorreRaton() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Botn tmido");
setLayout(new FlowLayout());
setBackground(Color.cyan);
// ventana centrada
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int ancho=300, alto=150;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
// preparamos la entrada de datos
Button botn = new Button("Plsame");
add(botn);
// escucha de teclado para la ventana
EscuchaRatn e = new EscuchaRatn(botn);
botn.addMouseListener(e);
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
// la mostramos
setVisible(true);
// si no hacemos esto el foco se lo queda la etiqueta!!!
requestFocus();
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {

System.exit(0);
}
}
class EscuchaRatn implements MouseListener {
Button botn;
// le pasamos el botn y el tamao de la pantalla
public EscuchaRatn(Button botn) {
this.botn = botn;
}
public void mouseEntered(MouseEvent e) {
Point p = botn.getLocation();
if (p.x<150) p.x = 160 + ((int)(Math.random()*120));
else p.x = 20 + ((int)(Math.random()*120));
p.y = 20 + ((int) (Math.random()*100));
botn.setLocation(p);
}
// no olvidar incluir estos mtodos!!
public void mouseClicked(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}

MouseMotionListener
Detecta los movimientos del ratn, y tambin cuando el ratn se arrastra pulsado (para
marcar zonas). Este interfaz tiene dos mtodos:

void mouseMoved(MouseEvent e): El ratn se ha movido sin estar pulsado


void mouseDragged(MouseEvent e): El ratn se ha movido estando pulsado.

5.- Estilos
5.1 Introduccin
5.2 Estilo FlowLayout
5.3 Estilo BorderLayout
5.4 Estilo GridLayout
5.5 Paneles

5.1 Introduccin
El estilo (o diseo) de un contenedor indica cmo se dispondrn los componentes bsicos
en l.
Se establece mediante el mtodo void setLayout(LayoutManager l) de la clase Container.
La clase LayoutManager es la clase de la que heredan todos los estilos (layouts). Cada
contenedor tiene un estilo por defecto. Por ejemplo, en el caso de Frame este
es BorderLayout, y en el de Panel FlowLayout.
Observacin: Aunque cada contenedor tiene un nico estilo, podemos mezclar estilos
incorporando contenedores dentro de contenedores. La clase Panel est pensada con este
propsito.
Igual que en los puntos anteriores, aqu no vamos a ver todos los estilos de los que dispone
Java (hay 21 estilos diferentes!), contentndonos con ver algunos de los ms comunes y
esperando que sea suficiente para captar la "filosofa" y que a partir de stos comprender el
resto sea ms sencillo.

5.2 Estilo FlowLayout


En este estilo los componentes se colocan uno al lado del otro, en la misma fila. Cuando no
caben ms se cambia de fila. El orden en el que se colocan es de izquierda a derecha y de
arriba a abajo. De los estilos slo nos interesarn, en general, sus constructoras, no los
mtodos que contienen:
Constructoras
Tiene 3 constructoras:

FlowLayout(): Constructora por defecto; cada fila se alinea al centro.


FlowLayout(int alineamiento): Indica si cada fila aparecer alineada al centro, a la
izquierda o a la derecha. Para ello define las constantes FlowLayout.CENTER,
FlowLayout.LEFT yFlowLayout.RIGHT.
FlowLayout(int alineamiento, int sepH, int sepV) : Como el anterior, pero
permitiendo indicar, adems, la separacin entre columnas y entre filas.

Ejemplo: Aadimos 10 botones para ver como se colocan en la ventana con FlowLayout
EstiloFlowLayout.java

import java.awt.*;
import java.awt.event.*;
public class EstiloFlowLayout extends Frame {

public EstiloFlowLayout() {
// titulo, estilo, tamao y posicin iniciales
setTitle("FlowLayout");
setBackground(Color.cyan);
setSize(300,200);
// componentes centrados a la derecha, con una distancia entre ellos
// de 20 pixels en x y 30 en y
setLayout(new FlowLayout(FlowLayout.RIGHT, 20,30));
// aadimos unos botones de pega
for (int i=0; i<10; i++)
add(new Button(" "+i+" "));
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {System.exit(0); }
}

El resultado es:

5.3 Estilo BorderLayout


Es el estilo por defecto de Frame.
El estilo BorderLayout divide el contenedor en 5 reas: Norte, Sur, Este, Oeste y centro,
indicadas por las 5
constantes: BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST, BorderLa
yout.WEST yBorderLayout.CENTER.
Cada componente puede ocupar un rea nicamente; y a ser posible debe ocuparla por
entero. Si se aaden dos componentes a la misma rea, slo ser visible el ltimo de ellos.
El rea que ocupa el componente se indica al incorporarlo al contenedor con add. Si no se
indica nada se colocar en el centro.
Constructoras

BorderLayout(): Constructora por defecto.


BorderLayout(int sepHorizontal, int sepVertical): Incluye la separacin en pixels
entre los componentes.

Ejemplo
Ventana.java

import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
public Ventana() {
// titulo, estilo, tamao y posicin iniciales
setTitle("BorderLayout");
setBackground(Color.cyan);
setSize(300,200);
// componentes centrados a la derecha, con una distancia entre ellos
// de 20 pixels en x y 30 en y
setLayout(new BorderLayout());
// creamos 5 botones
Button este = new Button("Este");
este.setBackground(Color.blue);
Button oeste = new Button("Oeste");
oeste.setBackground(Color.red);
Button norte = new Button("Norte");
norte.setBackground(Color.yellow);
Button sur = new Button("Sur");
sur.setBackground(Color.green);
Button centro = new Button("Centro");
centro.setBackground(Color.pink);
// aadimos botones en cada zona
add(este, BorderLayout.EAST);
add(oeste, BorderLayout.WEST);
add(norte, BorderLayout.NORTH);
add(sur, BorderLayout.SOUTH);
add(centro); // equivalente a: add(centro, BorderLayout.CENTER);
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) { System.exit(0); }
}

El resultado es:

Observacin: Casi nunca se inserta un botn directamente en un componente con


estilo BorderLayout. Lo normal es introducirlos en otro componente (por ejemplo en
un Panel) que a su vez se inserta en el contenedor de estilo BorderLayout.

5.4 Estilo GridLayout


Es un estilo que divide el contenedor en "casillas". Permite fijar el nmero de componentes
por fila y por columna. Todas las casillas sern del mismo tamao, tamao suficiente para
que quepan todos los componentes.
Los componentes se van colocando en la siguiente posicin libre, comenzando desde arriba
a la izquierda.
Constructoras

GridLayout(): Constructora por defecto: una sola fila y una sola columna; poco
usada.
GridLayout(int filas, int columnas): Nmero de filas y columnas.
GridLayout(int filas, int columnas, int sepHorizontal, int sepVertical): Adems del
tamao en filas y columnas indica la separacin horizontal y vertical entre los
componentes.

Ejemplo
Grid.java

import java.awt.*;
import java.awt.event.*;
public class Grid extends Frame {
public Grid() {
// titulo, estilo, tamao y posicin iniciales
setTitle("GridLayout");
setBackground(Color.yellow);

setSize(250,150);
// componentes en 4 filas, a 2 columnas,
// 10 pixels de separacin horizontal entre componentes
// y 5 pixels de separacin vertical
setLayout(new GridLayout(4,2,10,5));
add(new Label("Nombre: ", Label.RIGHT));
TextField nombre = new TextField(10);
add(nombre);
add(new Label("Apellidos: ", Label.RIGHT));
TextField apellidos = new TextField(20);
add(apellidos);
add(new Label("Direccin: ", Label.RIGHT));
TextField direccin = new TextField(30);
add(direccin);
Button continuar = new Button("Siguiente");
add(continuar);
Button abandonar = new Button("Cancelar");
add(abandonar);
// faltaran todas las escuchas para que el programa haga algo real
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) { System.exit(0);
}

El resultado es:

5.5 Paneles
La clase Panel representa un contenedor que no puede existir por su cuenta, slo insertado
en otro contenedor (como por ejemplo en un Frame(). Su estilo por defecto es FlowLayout,
aunque como en todos los contenedores se puede modificar con setLayout. Se utiliza a
menudo para combinar diferentes estilos en una misma ventana.

Observacin: Una fase importante al desarrollar aplicaciones con interfaz grficos es la


del diseo del interfaz: qu paneles compondrn cada ventana y con qu estilos.

Ejemplo: Vamos a escribir el aspecto previo que tendra una aplicacin para jugar al
ajedrez; incluyendo el tablero vaco, un ttulo inicial y botones para comenzar y salir. El
resultado debe ser:

Antes de escribir el programa pensamos en el diseo de la ventana:

Con este diseo podemos escribir el cdigo:


Tablero.java

import java.awt.*;
import java.awt.event.*;
public class Tablero extends Frame {
public Tablero() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Tablero");
setBackground(Color.green);
// ventana centrada
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int ancho=300, alto=350;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
// preparamos el layout de la ventana
setLayout(new BorderLayout(20,20));
// ponemos la etiqueta
Font fuente = new Font("Arial", Font.BOLD, 20);
Label etiq = new Label("A J E D R E Z ", Label.CENTER);

etiq.setFont(fuente);
etiq.setForeground(new Color(100,0,50));
add(etiq, BorderLayout.NORTH);
// preparamos el tablero; ser el panel central
Panel tablero = new Panel();
tablero.setLayout(new GridLayout(8,8));
for (int i=1; i<=8; i++)
for (int j=1; j<=8; j++)
if ((i+j) % 2 == 0) {
Button blanca = new Button(" ");
blanca.setBackground(Color.white);
blanca.setEnabled(false);
tablero.add(blanca);
}
else {
Button negra = new Button(" ");
negra.setBackground(Color.black);
negra.setEnabled(false);
tablero.add(negra);
}
// lo ponemos en el centro
add(tablero,BorderLayout.CENTER);
// tablero para los botones
Panel botones = new Panel();
Button empezar = new Button("Empezar");
Button acabar = new Button("Acabar");
// no dejamos que pulsen acabar si no se est jugando
acabar.setEnabled(false);
botones.add(empezar);
botones.add(acabar);
add(botones, BorderLayout.SOUTH);
// paneles para dejar margen a la izquierda y a la derecha
Panel izq = new Panel();
Panel der = new Panel();
add(izq,BorderLayout.EAST);
add(der,BorderLayout.WEST);
// aadimos la escucha para cerrar la ventana
addWindowListener(new ParaAcabar());
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

6.- Dibujando
6.1 Introduccin
6.2 La clase Canvas
6.3 La clase Graphics
6.4 Mostrando imgenes
6.5 Un poco de animacin

6.1 Introduccin
Cmo dibujar?
Para dibujar en Java hay que conocer inicialmente los siguiente conceptos.

Los objetos capaces de dibujar son los de tipo Graphics (descritos en el punto 4.6.3).
Contienen mtodos para dibujar lneas, rectngulos, imgenes ledas de un fichero
(formato .gif o jpeg) etc.
Todo componente grfico contiene un objeto de tipo Graphics, que es el que usa para
"dibujarse" a si mismo.
Todo componente grfico incluye un mtodo Graphics getGraphics()

De todo esto se deduce que para dibujar podemos "pedirle prestado" su objeto Graphics() al
componente en el que queramos dibujar. Ejemplo: Botn subrayado (primera versin).
Ventana.java

import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame{
public Ventana() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Botn con dibujo V.1");
setLayout(new FlowLayout());
Font fuente = new Font("Arial", Font.BOLD, 40);
setFont(fuente);
// ventana centrada
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int ancho=200, alto=90;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
Button botn = new Button("Aceptar");

add(botn);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
// la mostramos
setVisible(true);
// dibujamos sobre el botn
Graphics g = botn.getGraphics();
g.setColor(Color.green);
g.fill3DRect(5,40,70,10,true);
g.fill3DRect(80,40,90,10,true);
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

El resultado es:

El problema est en que cada vez que se repinta el botn no se vuelve a pintar la lnea. De
hecho el dibujo slo se hace una vez, al estar en la constructora, y cada vez que hay que
pintar el botn.
El mtodo paint
Para arreglar este problema hay que saber algunas cosas ms.

Cuando un objeto necesita repintarse, llama a su mtodo public void


update(Graphics g).
El comportamiento por defecto de update es:
o Borrar el componente.
o Llamar al mtodo public void paint(Graphics g) para dibujarlo de nuevo.
Nosotros no podemos llamar a estos mtodos directamente; pero podemos pedir a un
componente que se "repinte" con el mtodo public void repaint().

As pues, la solucin est en sobreescribir el mtodo paint() del componente en el que


queremos dibujar; y para ello deberemos hacer una nueva clase que herede de la clase de
dicho componente, tal y como muestra el siguiente ejemplo: Ejemplo: Botn subrayado
(segunda versin).
BotonSubrayado.java

import java.awt.*;
public class BotonSubrayado extends Button {
public BotonSubrayado(String nombre) {
super(nombre);
}
public void paint(Graphics g) {
// llamamos al pintar original
super.paint(g);
g.setColor(Color.green);
g.fill3DRect(5,40,70,10,true);
g.fill3DRect(80,40,90,10,true);
}
}

Ventana.java

import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame{
public Ventana() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Botn con dibujo V.1");
setLayout(new FlowLayout());
Font fuente = new Font("Arial", Font.BOLD, 40);
setFont(fuente);
// ventana centrada
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int ancho=200, alto=90;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
BotonSubrayado botn = new BotonSubrayado("Aceptar");
add(botn);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
// la mostramos
setVisible(true);
Graphics g = botn.getGraphics();
g.setColor(Color.green);
g.fill3DRect(5,40,70,10,true);
g.fill3DRect(80,40,90,10,true);
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {

System.exit(0);
}
}

Ahora cada vez que haya que volver a pintar el botn se dibujar tambin la lnea

6.2 La clase Canvas


Aunque hemos visto que se puede dibujar en cualquier componente, lo normal es querer
dibujar slo en un espacio en blanco destinado a tal fin. Con este propsito se incluye en
java el componente Canvas. El procedimiento para incluir grficos como parte de una
ventana es:
1. Declarar una clase que herede de canvas.
2. Sobrescribir el mtodo void paint(Graphics g) (y/o void update(Graphics g)) de la
nueva clase de forma que se dibuje el grfico deseado.
3. Aadir un objeto de la clase nueva como componente de la ventana.
Una aplicacin hecha siguiendo esta idea tendr al menos tres clases, con la siguiente
estructura:
Lienzo.java
import java.awt.*;
// clase para dibujar
public class Lienzo extends Canvas {
...
// aqu se incluir el cdigo para dibujar
public void paint(Graphics g) {
....
}
.....
}

Ventana.java
import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
......
public Ventana() {
....
....
Lienzo l = new Lienzo();

add(l);
.......
......
}
}
......

Principal.java
public class Principal {
public static void main(String[] args) {
new Ventana();
}
}

6.3 La clase Graphics


De esta clase no nos interesan sus constructoras, porque nunca vamos a construir un
objeto Graphics; slo vamos a utilizar un objeto ya existente.

Mtodos Principales
abstract

void clearRect(int x, int y, int width, int height)

Borra el rectngulo especificado por sus parmetros; es decir lo pinta del


color de fondo.
abstract

void copyArea(int x, int y, int width, int height, int dx,


int dy)

Copia el rea del componente especificada por los parmetros a una


distancia dx and dy. Si se quiere que se copie a la izquierda habr que dar
un valor dx negativo. Anlogamente, para copiar ms arriba de la posicin
actual habr que indicar un valor dy negativo.
void draw3DRect(int x, int y, int width, int height,
boolean raised)

Dibuja un rectngulo al que se da aspecto de 3d, bien mostrndolo


ligeramente elevado (si raised es true) o hundido (raised false)
abstract

void drawArc(int x, int y, int width, int height, int startAngle,


int arcAngle)
Dibuja un arco (circular o elptico), empezando en el ngulo startAngle y
finalizando en arcAngle. El arco estar inscrito en el rectngulo indicado

por los parmetros, con centro en el centro de dicho rectngulo.


Ejemplo: El siguiente arco est escrito con la
instruccin g.drawArc(50,50,150,100,0,260);. Tambin se muestra en
el dibujo el rectngulo (dibujado con g.drawRect(50,50,150,100);).

abstract

boolean drawImage(Image img, int x, int y, Color bgcolor,


ImageObserver observer)
Dibuja la imagen. Las coordenadas (x,y) marcan donde estar situada la
esquina superior izquierda del dibujo y bgcolor el fondo que se mostrar
en la parte transparente de la imagen. El parmetro observer indica un

objeto al que se va avisando cuando segn se va mostrando la imagen.


Nosotros lo lo utilizaremos y lo pondremos a null.
abstract

boolean drawImage(Image img, int x, int y, ImageObserver observer)

Anlogo al anterior. El color de fondo no vara.


abstract

boolean drawImage(Image img, int x, int y, int width,


int height, bgcolor, ImageObserver observer)

Anlogo a los anteriores con la salvedad de que el grfico se reescalar para


ajustarse al rectngulo indicado.
abstract

boolean drawImage(Image img, int x, int y, int width, int height,


ImageObserver observer)

Anlogo al anterior.
abstract

void drawLine(int x1, int y1, int x2, int y2)

Dibuja una lnea, en el color actual, entre los dos puntos.


Observacin: Si el punto final es igual al inicial se dibuja un punto. Esto
es importante porque no existe ningn mtodo para dibujar puntos, por lo
que lo normal es utilizar drawLine(x,y,x,y).
abstract

void drawOval(int x, int y, int width, int height)


Dibuja un valo inscrito en el rectngulo indicado. Si width = height

se

dibujar una circunferencia


abstract

void drawPolygon(int[] x, int[] y, int n)

Dibuja un polgono. Para ello traza las rectas (x[0],y[0]),


(x[1],y[1]) ... (x[n-2],y[n-2]), (x[n-1],y[n-1]), (x[n-1],y[n-1]), (x[0],y[0]).
abstract

void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)

Dibuja una secuencia de lneas. La diferencia con drawPolygon es que no


incluye la ltima lnea para "cerrar" el polgono.
void drawRect(int x, int y, int width, int height)

Dibuja un rectngulo.
abstract

void drawRoundRect(int x, int y, int width, int height,

int arcWidth, int arcHeight)

Dibuja un rectngulo con los ngulos "redondeados".


abstract

void drawString(String str, int x, int y)

Muestra la cadena. El punto (x,y) representa la posicin inicial (marcada


por un punto en la figura de abajo) para el primer carcter de la cadena.

void fill3DRect(int x, int y, int width, int height,


boolean raised)

Anlogo a draw3DRect pero dibujando el rectngulo relleno con el color


actual.
abstract

void fillArc(int x, int y, int width, int height, int startAngle,


int arcAngle)

Anlogo a drawArc pero dibujando el arco relleno con el color actual.


abstract

void fillOval(int x, int y, int width, int height)

Anlogo a fillOval pero con el valo relleno del color actual.


abstract

void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)

Anlogo a drawPolygon pero rellenando el polgono con el color actual.


abstract

void fillRect(int x, int y, int width, int height)

Anlogo a drawRect pero rellenando el rectngulo del color actual.


abstract

void fillRoundRect(int x, int y, int width, int height,


int arcWidth, int arcHeight)

Anlogo a drawRoundRect pero rellenando el rectngulo redondeado con el


color actual.
void finalize()

Para liberar la memoria requerida por un objeto Graphics que ya no es


necesario. Esto se hace porque los objetos Graphics son muy costosos en
cuanto a recursos de memoria.
abstract

Color getColor()

Devuelve el color actual.


abstract

Font getFont()

Devuelve la fuente (tipo de letra) actual.


FontMetrics getFontMetrics()

Devuelve un valor de tipo FontMetrics representando las caractersticas


mtricas de la fuente de letra actual. La clase FontMetrics contiene diversos
mtodos para conocer las medidas de los caracteres dentro del tipo actual.
Por ejemplo el mtodo stringWidth(String cadena) devolver la anchura en
pixels requerida para mostrar la cadena.
abstract

FontMetrics getFontMetrics(Font f)

Devuelve las caractersticas mtricas de la fuente de letra que se le pasa


como parmetro.
abstract

void setColor(Color c)

Cambia el color actual al color indicado.


abstract

void setFont(Font font)

Establece la nueve fuente de letra.


abstract

void setPaintMode()

Indica que al dibujar se borra el fondo. Es el modo de actuacin por defecto.


abstract

void setXORMode(Color c1)

Al dibujar los pixels que sean del color de fondo se cambian al color del
parmetro y viceversa.
String toString()

Representacin como cadena de caracteres del objeto Graphics.


abstract

void translate(int x, int y)

Fija un nuevo centro de coordenadas.

6.4 Mostrando imgenes


Para mostrar imgenes que estn en disco en forma .gif o .jpg podemos seguir el
procedimiento siguiente:
1. Leer la imagen del fichero con el
mtodo Toolkit.getDefaultToolkit().getImage(String nombre). En la que el nombre es
el nombre del fichero. Este mtodo devuelve un valor de tipo Image, por lo que la
instruccin podra ser del estilo:
Image img = Toolkit.getDefaultToolkit().getImage("foto.gif");

2. La clase Image es la que se utiliza para representar imgenes genricas en Java.


3. Utilizar el mtodo showImage de Graphics. Este mtodo esta sobrecargado tal y
como vimos en el punto anterior.
Ejemplo: Vamos a mostrar una secuencia de imgenes para producir el efecto de una
animacin.
Saluda.java
import java.awt.*;
import javax.swing.*;
public class Saluda extends Canvas
Image t[]; // array de imgenes
public Saluda() {

t = new Image[10];
for

(int i = 0; i<10; i++)


t[i] = Toolkit.getDefaultToolkit().getImage("t"+(i+1)+".gif");

}
public void paint(Graphics g) {
g.drawImage(t[0],0,0, 200,200, Color.white, null);
}
public void saluda() {
Graphics g = getGraphics();
for (int i = 1; i<10; i++) {
g.drawImage(t[i],0,0,200,200, Color.white, null);
// perdemos un poco de tiempo para que se vea
try{ Thread.sleep(150);} catch(Exception e) {}
}
repaint();
}
}

Ventana.java

import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
public Ventana() {
// titulo, estilo, tamao y posicin iniciales
setTitle("saluda a los seores");
// ventana centrada
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int ancho=200, alto=250;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
// el lienzo ir en el centro de la pantalla
Saluda lienzo = new Saluda();
add(lienzo);
// el botn con su escucha correspondiente
Button boton = new Button("saluda!");
Escucha e = new Escucha(lienzo);
boton.addActionListener(e);

add(boton, BorderLayout.SOUTH);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
// la mostramos
setVisible(true);
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
// escucha del boton
class Escucha implements ActionListener {
Saluda lienzo;
public Escucha(Saluda lienzo) {
this.lienzo = lienzo;
}
public void actionPerformed(ActionEvent e) {
lienzo.saluda();
}
}

Principal.java
public class Principal {
public static void main(String[] args) {
new Ventana();
}
}

6.5 Un poco de animacin


Vamos a mostrar por medio de un ejemplo un par de tcnicas sencillas que se pueden
utilizar para mejorar animaciones de grficos. El ejemplo consiste en una pelota que se
mueve rebotando contra las paredes de la ventana.
Versin inicial
La idea es, como siempre, sobreescribir la clase paint del lienzo para que dibuje un circulo
(la pelota), pero de forma que la posicin de la pelota dependa de unas variables x, y, y

escribir un mtodo que modifique estas variables y obligue al lienzo a repintarse para
simular la animacin.
Principal.java

public class Principal {


static public void main(String [] args) {
new Ventana();
}
}

Ventana.java

import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
public Ventana() {
// titulo, estilo, tamao y posicin iniciales
setTitle("Animacin - V1");
// ventana centrada
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int ancho=400, alto=250;
setSize(ancho, alto);
setLocation(d.width/2-ancho/2,d.height/2-alto/2);
// el lienzo ir en el centro de la pantalla
CorrePelota lienzo = new CorrePelota();
add(lienzo);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
// la mostramos
setVisible(true);
// buclew de animacin
for (long i=0; i<10000000; i++) {
// mover la pelota
lienzo.correCorre();
// perder el tiempo
try { Thread.sleep(10); } catch(Exception e) {}
}
}
}
// clase para cerrar la ventana

class ParaAcabar extends WindowAdapter {


public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

CorrePelota.java
import java.awt.*;
public class CorrePelota extends Canvas {
private final int radio = 30;
int x = 20,y = 20; // pos. inicial
int incX = 1, incY = 1; // dir. inicial
public CorrePelota() {
setBackground(Color.black);
setForeground(Color.yellow);
}
public void correCorre() {
// calculamos la nueva posicin de la pelota
x += incX; y += incY;
// si hay choque invertimos la direccin
if (x>370)
incX = -((int) (Math.random()*2+1));
if (x<0)
incX = (int) (Math.random()*2+1);
if (y>190)
incY = -((int) (Math.random()*2+1));
if (y<0)
incY = (int) (Math.random()*2+1);
repaint();
}
public void paint(Graphics g) {
g.fillOval(x,y,radio,radio);
}
}

El programa funciona, pero la pelota al moverse tiene un extrao "parpadeo". Vamos a ver
como solucionarlo.
Yo me lo pinto y yo me lo borro
El problema es que antes de pintar el nuevo dibujo debe borrarse el anterior; y de eso se
encarga update, que antes de llamar a paint borra el lienzo completo.

Como esto tarda en hacerse en ocasiones el refresco de pantalla "pilla" a la animacin justo
despus de borrar la figura pero antes de volver a dibujarla y eso provoca el parpadeo. Una
solucin es impedir que update() borre la figura anterior y en su lugar hacerlo nosotros, que
en lugar de borrar todo el grfico slo borraremos la figura anterior.
Para hacer esto slo tenemos que modificar la clase CorrePelota:
CorrePelota.java
import java.awt.*;
public class CorrePelota extends Canvas {
private final int radio = 30;
int x = 20,y = 20; // pos. inicial
int incX = 1, incY = 1; // dir. inicial
int antx, anty; // posicin antigua de la pelota
public CorrePelota() {
setBackground(Color.black);
setForeground(Color.yellow);
}
public void correCorre() {
// guardamos la posicin antigua para borrarla
antx = x; anty = y;
// calculamos la nueva posicin de la pelota
x += incX; y += incY;
// si hay choque invertimos la direccin
if (x>370)
incX = -((int) (Math.random()*2+1));
if (x<0)
incX = (int) (Math.random()*2+1);
if (y>190)
incY = -((int) (Math.random()*2+1));
if (y<0)
incY = (int) (Math.random()*2+1);
repaint();
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
// borramos la anterior
g.clearRect(antx,anty,radio,radio);
g.fillOval(x,y,radio,radio);
}
}

Aunque el parpadeo disminuye ligeramente sigue existiendo; se tarda demasiado en dibujar


el valo.
Doble buffer
La idea es no dibujar ni borrar directamente en la pantalla, sino en un objeto de
tipo Image que nos har de "buffer" o de copia del lienzo. Una vez que hayamos dibujado
en el objeto slo tendremos que volcarlo a pantalla con drawImage. As el usuario no podr
ver el proceso de borrado y dibujado; slo la figura en la nueva posicin.
La nueva versin de la clase CorrePelota es:
CorrePelota.java
import java.awt.*;
public class CorrePelota extends Canvas {
private final int radio = 30;
int x = 20,y = 20; // pos. inicial
int incX = 1, incY = 1; // dir. inicial
int antx, anty; // posicin antigua de la pelota
// el doble buffer
Image copia;
Graphics gCopia;
boolean primeraVez = true;
public CorrePelota() {
setBackground(Color.black);
setForeground(Color.yellow);
}
public void correCorre() {
// guardamos la posicin antigua para borrarla
antx = x; anty = y;
// calculamos la nueva posicin de la pelota
x += incX; y += incY;
// si hay choque invertimos la direccin
if (x>370)
incX = -((int) (Math.random()*2+1));
if (x<0)
incX = (int) (Math.random()*2+1);
if (y>190)
incY = -((int) (Math.random()*2+1));
if (y<0)
incY = (int) (Math.random()*2+1);
repaint();
}
public void update(Graphics g) {

// para que la pinte


paint(g);
}
public void paint(Graphics g) {
if (primeraVez) {
copia = createImage(400,250);
gCopia = copia.getGraphics();
primeraVez = false;
}
gCopia.clearRect(antx,anty,radio,radio);
gCopia.fillOval(x,y,radio,radio);
g.drawImage(copia,0,0,this);
}
}

Observacin: En swing existen mtodos especficos para tratar el doble buffer que
permiten mostrar animaciones de mejor calidad.

7.- Applets

7.1 Qu es un Applet?
7.2 Pginas WEB
7.3 Vida (y muerte) de un Applet
7.4 Ejemplo

7.1 Qu es un Applet?

Un applet es un programa Java que se ejecuta dentro de una pgina html. El cdigo (.class)
viaja junto con la pgina al ordenador del usuario, donde es ejecutado por la mquina
virtual del explorador correspondiente.
Observacin: Para que se pueda ver el applet dentro de la pgina hay que tener activada
la mquina virtual de Java del explorador
Los applets son especialmente utilizados en pginas de tipo cientfico y pedaggicas, para
ilustrar conceptos, simular experimentos. Un ejemplo tpico es cuando en nuestra pgina
queremos mostrar un grfica que depende de ciertos parmetros introducidos por el usuario.

7.2 Pginas WEB


Pginas html
Una pgina WEB es, normalmente un texto escrito en el lenguaje html. La forma ms
simple de una pgina en html es

pagina.html
<html>
<head>
<title> Una pgina </title>
</head >
<body >
Esta es una pgina mnima
</body>
</html>

Podemos escribir este texto en un fichero (por ejemplo con el block de notas), grabarlo y
abrirlo con el explorador. En general una pgina html puede contener:

Texto (se incluye el texto sin ms)


Imgenes (Ej.: <img src="dibu.jpg"> para incluir dibu.jpg en la pgina )
Enlaces a otras pginas (Ej.: Si incluimos <a
href="http://www.ucm.es">ucm</a> aparecer la palabra ucm y al pulsar sobre ella
se saltar a la pgina de la universidad complutense).

Sin embargo no puede incluir acciones dinmicas, como por ejemplo pedir datos al usuario,
procesarlos y mostrar el resultado, o mostrar una animacin
Incluyendo Java en pginas WEB
La llamada al cdigo java se introduce mediante el delimitador html applet
<html>
<head>
<title> Un mini-applet </title>

</head >
<body >
Aqu incluimos una llamada al applet: <p>
<applet code=Mini.class" width=150 Height=25></applet> <p>
Y luego seguimos con el texto de la pgina
</body>
</html>

El resultado es:

Importante: El cdigo java compilado (Mini.class en el ejemplo) debe encontrarse en


la misma carpeta que la pgina html.

7.3 Vida (y muerte) de un Applet


Para escribir un applet debemos escribir una clase que herede de la clase Applet (import
java.applet.*). Hay 4 mtodos en esta clase que nos interesan:
1. init(): Inicializa el applet. Es en esta funcin (y no en la constructora) donde debemos
crear todos los componentes del applet e insertarlos.
2. start(): se llama una vez creado el applet, para que comience la ejecucin. Por
ejemplo en una animacin sera start quien comenzara el movimiento. En este punto
conviene ser cuidadosos: si start entra en un bucle sin fin puede dejar "colgada" la

pgina. para solucionar esto se utilizan hebras (Threads) que se ejecutan de forma
concurrente sin bloquear la pgina.
3. stop(): Se ha detenido el applet. Se puede volver a iniciar con start().
4. destroy(): Limpieza final y eliminacin del applet.

7.4 Ejemplo
El siguiente ejemplo mueve un dibujo ''cab.gif'' por la pantalla. Usa hebras (que no han sido
explicadas en clase: interfaz Runnable y funcin run()).

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Imagen extends Applet implements Runnable{
Image coche;
int x=600,y=20;
Thread corre = new Thread(this);
//Inicializar el applet
public void init() {

MediaTracker tracker = new MediaTracker(this);


coche = getImage(getCodeBase(),"cab.gif");
tracker.addImage(coche, 1);
try { tracker.waitForAll();} catch(Exception e) {e.printStackTrace();}
this.setBackground(Color.white);
}
public void run() {
try {
Thread.sleep(1000);
} catch (Exception e) {;}
while (true) {
repaint();
try {
Thread.sleep(40);
} catch (Exception e) {;}
}
}
public void start() {
corre.start();
}
public void paint(Graphics g) {
update(g);
}
public void update(Graphics g) {
x--;
g.drawImage(coche,x,y,70,50,Color.white,this);
if (x==-70) x = 600; // volvemos a empezar
}
}

8.- Dilogos y Mensajes


8.1 La clase Dialog
8.2 La clase FileDialog
8.3 La clase JOptionPane

8.1 La clase Dialog


Los dilogos son ventanas "hijas" de la ventana principal que se utilizan normalmente para
mostrar informacin, errores, o pedir confirmacin. El ejemplo ms habitual es la ventana
con el mensaje "Desea salir de la aplicacin?" con los botones de aceptar y cancelar. Hay
dos tipos de dilogos:

Dilogos modales: No se puede actuar sobre la aplicacin hasta que no se haya


cerrado el dilogo. Son los ms comunes.
Dilogos no modales: No necesitan cerrarse para seguir trabajando sobre la
aplicacin.

Dado que los dilogos son un tipo especial de ventanas, no tenemos que describir sus
mtodos, tan slo sus constructoras:
Constructoras

Dialog(Frame prop): Crea un dilogo no visible (hasta que se haga setVisible(true)),


no modal y con ttulo vaco. prop es el nombre del dilogo o la ventana propietaria.
Si se desea se puede poner null para indicar que no tiene ventana "madre".
Dialog(Frame prop, String titulo): Anlogo al anterior pero indicando el ttulo.
Dialog(Frame prop, String titulo, boolean modal): Si modal es true crea una ventana
modal.

8.2 La clase FileDialog


Es un caso especial de dilogo modal orientado a la seleccin de ficheros (a menudo
asociados a opciones del estilo de "Abrir" o "Guardar como"). Hay que tener en cuenta que
el dilogo slo selecciona nombres de ficheros; no abre ni guarda nada.
Constructoras
La constructora ms completa tiene la sintaxis:
FileDialog(Frame vent, String msg, int mode)

Donde vent es la ventana madre, msg es el ttulo del cuadro de dilogo y mode debe ser o
bien FileDialog.LOAD si el dilogo se utiliza para abrir un fichero o FileDialog.SAVE si se
utiliza para grabar un fichero.
Mtodos

String getDirectory(): Cadena con el directorio que contiene el fichero seleccionado.


String getFile(): Cadena con el nombre del fichero seleccionado.
FilenameFilter getFilenameFilter(): Filtro utilizado en la seleccin.
int getMode(): Devuelve el modo: FileDialog.LOAD o FileDialog.SAVE.
void setDirectory(String dir) : Establece el directorio inicial que se mostrar al abrir
el dilogo.
void setFile(String nombreFich): Nombre por defecto del fichero; se usa
habitualmente en los dilogos de guardar.
void setFilenameFilter(FilenameFilter f): Filtro que se utilizar para mostrar los
archivos en el cuadro de dilogo.
void setMode(int modo): Pone el modo a FileDialog.LOAD o FileDialog.SAVE.

Adems de estos mtodos es interesante conocer la constante File.separator que indica el


separador de directorios (la barra inclinada hacia la derecha o la izquierda dependiendo del
sistema operativo).
El siguiente ejemplo ilustra como se puede utilizar este dilogo para abrir un fichero:

import java.awt.*;
import java.awt.event.*;
public class Ventana extends Frame {
public Ventana() {
setTitle("Entrada de datos");
setLayout(new FlowLayout());
setSize(300,100);
setLocation(300,200);
Label etiqInfo = new Label("Fichero seleccionado: ");
Label etiqSel = new Label();
add(etiqInfo);
add(etiqSel);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
// la mostramos
setVisible(true);
// creamos un dialogo para abrir un fichero
FileDialog fd = new FileDialog(this, "Abrir...",FileDialog.LOAD);
// al abrir el dialogo, como es modal, la aplicacin queda
// bloqueada
fd.setVisible(true);
String fname = fd.getFile();
// si el usuario ha cancelado el dialogo se devuelve null
if (fname != null) {
String fdir = fd.getDirectory();
String name = fdir + fname;
// mostramos el nombre elegido en la ventana
etiqSel.setText(name);
} // if
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

8.3 La clase JOptionPane


Los dilogos ms comunes son los dilogos modales que se utilizan para presentar
informacin, o bien informar de un error, y que incluyen un botn Aceptar o bien
botones Aceptar y Cancelar. Por eso en swing se incluyo una clase especial para representar
este tipo de dilogos, la clase JOptionPane, que resulta muy til a la hora de presentar
informacin debido a su sencillez.
Observacin: Es posible (y bastante normal) mezclar en una misma aplicacin
componentes awt con componentes swing.
Los principales mtodos de esta clase son cuatro mtodos estticos:

showConfirmDialog: Dilogo para pedir confirmacin, como los tpicos dilogos con
los botones si/no/cancelar.
showInputDialog: Para pedir una entrada de datos al usuario.
showMessageDialog: Informacin para el usuario, con un botn de aceptar.
showOptionDialog: Combina las posibilidades de los tres anteriores.

Tambin hay 5 constantes que pueden utilizarse para indicar el tipo de mensaje que se est
mostrando. La seleccin de la constante adecuada influir en el icono que se presentar en
la ventana modal:

ERROR_MESSAGE
INFORMATION_MESSAGE
WARNING_MESSAGE
QUESTION_MESSAGE
PLAIN_MESSAGE

Por ltimo, aunque podemos incluir en el dilogo los botones que deseemos, hay 4
constantes que definen los conjuntos de botones ms usuales:
DEFAULT_OPTION YES_NO_OPTION YES_NO_CANCEL_OPTION OK_CANCE
L_OPTION
El primero muestra slo un botn de aceptar (el significado del resto es obvio a partir del
nombre). Vamos a ver algunos ejemplos en el siguiente programa:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*; // para JOptionPane
public class Ventana extends Frame {
public Ventana() {
setTitle("Entrada de datos");
setLayout(new FlowLayout());

setSize(200,100);
setLocation(300,200);
// el primer argumento es la ventana madre,
// el segundo el mensaje a mostrar, el tercero el titulo
// de la ventana y el cuarto el tipo de dialogo
JOptionPane.showMessageDialog(this,
"El fichero se ha grabado correctamente",
"informacion", JOptionPane.INFORMATION_MESSAGE);
// muestra el dialogo con un simbolo de interrogacion
if (JOptionPane.showConfirmDialog(null,
"desea salir de la aplicacion?", "aviso",
JOptionPane.YES_NO_OPTION) == 0)
System.exit(0);
// igual pero con un simbolo de informacion
JOptionPane.showConfirmDialog(this,
"Desea continuar?", "informacion",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.INFORMATION_MESSAGE);
// para pedir un dato
String nombre =
JOptionPane.showInputDialog("Su nombre:");
// elegir un dato de una lista
Object[] valores = { "Norte","Sur", "Este","Oeste" };
Object selectedValue =
JOptionPane.showInputDialog(
null, // ventana madre
"Elige una direccion", // mensaje
"Direcciones", // titulo
JOptionPane.INFORMATION_MESSAGE, // tipo mensaje
null, // icono
valores, // valores
valores[0] // valor marcado inicialmente
);
// aadimos el "listener" para cerrar la ventana
addWindowListener(new ParaAcabar());
}
}
// clase para cerrar la ventana
class ParaAcabar extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

Este programa muestra las siguientes ventanas de dilogo (consecutivamente, cada una tras
cerrar la anterior):

Você também pode gostar