65
Tema 5: Desarrollo de aplicaciones gráficas 1.- Introducción 2.- Ventanas: la clase Frame 3.- Componentes Básicos 4.- Eventos de teclado y de ratón 5.- Estilos 6.- Dibujando 7.- Applets 8.- Diálogos y mensajes Apéndice A: Un poquito de Swing 1.- Introducción 1.1 AWT y Swing 1.2 Un poco de filosofía 1.3 La jerarquía 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 diseño de interfaces gráficas. En otros lenguajes (C, C++, etc.), las librerías de componentes gráficos dependían del fabricante del compilador particular que se decidiera utilizar. Esto favorecía la aparición de dialectos del lenguaje y la falta de uniformidad en el modelo propuesto. La variedad de clases gráficas y sus inmensas posibilidades de diseño hacer que un buen programador en Java no sea sólo aquel que conoce los aspectos básicos del lenguaje y su filosofía; es necesario también un conocimiento detallado de las clases del API (application program interface) de Java y sus posibilidades.

Aplicaciones Graficas en Java

Embed Size (px)

DESCRIPTION

Programacion

Citation preview

  • 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 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

    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. // preparamos la escucha del boton 40. Escucha e = new Escucha(etiq); 41. // la registramos 42. boton.addActionListener(e); 43. 44. 45. // aadimos el "listener" para cerrar la ventana 46. addWindowListener(new ParaAcabar()); 47. 48. // la mostramos 49. setVisible(true); 50. 51. } 52. } 53. 54. 55. // clase para cerrar la ventana 56. class ParaAcabar extends WindowAdapter { 57. public void windowClosing(WindowEvent e) { 58. System.exit(0); 59. } 60. } 61. 62. 63. // escucha del boton 64. class Escucha implements ActionListener { 65. int i; // para contar las veces que se ha pulsado 66. Label etiqueta; // etiqueta que se modificar 67. 68. 69. public Escucha(Label etiqueta) { 70. this.etiqueta = etiqueta; 71. i=0; 72. } 73. 74. public void actionPerformed(ActionEvent e) { 75. i++; 76. etiqueta.setText("Has pulsado "+i+" veces"); 77. } 78. } 79.

    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. package ventanas; 86. 87. import java.awt.*; 88. 89. import java.awt.*; 90. import java.awt.event.*; 91. 92. public class Ventana extends Frame { 93. private int contador; 94. private Label etiq; 95. private Button botn; 96. 97. // constructora 98. public Ventana() { 99. contador = 0; 100. 101. // titulo, estilo, tamao y posicin iniciales 102. setTitle("Ejemplo de ventana con boton (v.3) "); 103. setLayout(new FlowLayout()); 104. setSize(300, 100); setLocation(100,50); 105. 106. // le damos un poco de color a la ventana 107. setBackground(Color.yellow); 108. 109. // una etiqueta 110. etiq = new Label("An no has pulsado"); 111. add(etiq); 112. 113. // creamos el boton 114. botn = new Button("Plsame"); 115. botn.setBackground(Color.blue); 116. botn.setForeground(Color.white); 117. 118. // incorporamos el boton al frame 119. // importante: si no se hace esto no sera visible 120. add(botn); 121. 122. // preparamos la escucha del boton 123. Escucha e = new Escucha(); 124. // la registramos 125. botn.addActionListener(e); 126. 127. // aadimos el "listener" para cerrar la ventana 128. addWindowListener(new ParaAcabar()); 129. } 130. 131. // escucha del botn 132. private class Escucha implements ActionListener { 133. public void actionPerformed(ActionEvent e) { 134. contador++; 135. etiq.setText("Has pulsado "+contador+" veces"); 136. } 137. } 138. } // fin de la clase Ventana 139. 140. // clase para cerrar la ventana 141. 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

  • 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

  • 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

  • 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[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

  • 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

  • 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 (x190)

    incY = -((int) (Math.random()*2+1));

    if (y

  • 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 (x190)

    incY = -((int) (Math.random()*2+1));

    if (y

  • 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 bu