Está en la página 1de 69

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

Descripcin

String getName()

Devuelve el nombre del componente

void setName(String)

Para fijar el nombre del componente

Dimension1 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, int height)

Llamaremos a este mtodo para pedirle al componente


que redibuje el 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
Contenedores

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.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.

// creamos el boton
Button boton = new Button("Plsame");
boton.setBackground(Color.blue);
boton.setForeground(Color.white);
// incorporamos el boton al frame
// importante: si no se hace esto no sera visible
add(boton);
// 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:

81.

82.
83.
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.

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());

130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.

// 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 {
public void windowClosing(WindowEvent e) {System.exit(0);}
}

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);
ellos

// componentes centrados a la derecha, con una distancia entre


// 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.EA
ST, BorderLayout.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 parmetroobserver 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[n1]), (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 getFontMetrics(Font f)
FontMetrics

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_CANCEL_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):

2004-2006 Rafael Caballero

También podría gustarte