5.6 EVENTOS MÚLTIPLES FUENTES

 

Hola, ¿qué tal? Para explicar las fuentes en Java, como ejemplo vamos a fijarnos en un procesador de texto como LibreWriter, Word, Pad… estos procesadores tienen una serie de objetos, fuentes de eventos así como objetos oyentes de eventos. Si escribimos una frase o una palabra, la seleccionamos y pulsamos el botón de negrita, el texto se convierte en negrita. Hay que determinar quién es el objeto fuente del evento que en este caso sería el botón de negrita y el objeto oyente del evento sería el texto. 

Sin embargo, la negrita la puedo poner de varias formas, con el botón y con una combinación de teclas, por lo que sigue habiendo un objeto oyente pero hay varias fuentes.

En Java para registrar un objeto oyente con varias fuentes se utilizan la interfaz Action con sus respectivos métodos los cuales estamos obligados a declarar.



La interfaz Action() hereda del método actionPerformed(ActionEvent e), no tiene clase adaptadora por lo que nos obliga si o si declarar todos los métodos, no obstante, hay una clase AbstractAction que implementa el método actionPerformed(ActionEvent e),  sin necesidad de declararlos todos. Recomiendo ir a la API de Java para ver el uso de esta interfaz así como sus métodos.

El método setEnable() nos permite tener habilitado o no un objeto fuente de evento, por ejemplo, en el caso del procesador de texto, si no tenemos el texto seleccionado el botón Copiar está deshabilitado porque no hay nada que copiar, pero si seleccionamos el texto este botón se habilita.

En cuanto al método isEnabled() si el objeto fuente está activado o no dependerá del objeto oyente, es decir, el objeto oyente que es el texto si esta seleccionado el botón Copiar se habilitará, si no está seleccionado no se habilita, y este funcionamiento que se active o no el botón depende de las propiedades del objeto oyente que se determinan con la utilización de estos dos métodos: addPropertyChangedListener(PropertyChangedListener oyentes) y removePropertyChangedListener(PropertyChangedListener oyentes).

Pero para que nos quede más claro todo este galimatías de interfaz y de métodos es mejor con la práctica, vamos a crear una lámina que contenga tres botones que al pulsar sobre ellos el fondo de la lámina cambie de color, está practica ya la hicimos pero con la novedad que ahora también se va a poder cambiar el fondo de la lámina utilizando una combinación de teclas, el código de la práctica es el siguiente:

package event;

 

import javax.swing.*;

 

public class MultiplesFuentes {

 

       public static void main(String[] args) {

           

             MarcoFuentes mimarco=new MarcoFuentes();

           

             mimarco.setVisible(true);

           

             mimarco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

       }

 

}

 

class MarcoFuentes extends JFrame{

     

       public MarcoFuentes() {

           

             setTitle("Práctica MarcoFuentes");

           

             setSize(400, 400);

           

             LaminaFuentes milamina =new LaminaFuentes();

           

             add(milamina);

           

       }

}

 

class LaminaFuentes extends JPanel{

 

     

}

Es un código ya hemos visto así que no es necesario su explicación. Dentro de la clase LaminaFuentes vamos a crear el constructor y dentro de él vamos a crear los tres botones y añadirlos a la lámina:

class LaminaFuentes extends JPanel{

    public LaminaFuentes() {

       

        JButton BotonAmarillo=new JButton("Amarillo");

        JButton BotonAzul=new JButton("Azul");

        JButton BotonRojo=new JButton("Rojo");

      

        add(BotonAmarillo);

        add(BotonAzul);

        add(BotonRojo);

  }

     

}

Después de esto hay que poner a la lámina a la escucha para cuando pulsemos un botón cambie el fondo de la lámina, para ello tenemos que crearnos una clase que implemente la interfaz Action o bien herede de la clase AbstractAction

Creamos la clase que va a heredar de la clase AbstractAction

class ActionColor extends AbstractAction {

 

      @Override

      public void actionPerformed(ActionEvent e) {

            // TODO Auto-generated method stub

           

      }

     

}

Lo que vamos a determinar que tenga estos botones es un nombre, un icono, una descripción y la acción.

El nombre y el icono tenemos claro lo que es, la descripción es sin pulsar el botón simplemente con el puntero situarnos sobre él nos aparece una pequeña descripción y la acción que va a rellenar de color el fondo de la lámina.

Para ello en la clase ActionColor nos creamos un constructor que le vamos a pasar como parámetros el nombre, el icono y el color del botón:

class ActionColor extends AbstractAction {

     

    public ActionColor(String nombre, Icon icono, Color color_boton) {

       

       

    }

 

 

      @Override

      public void actionPerformed(ActionEvent e) {

            // TODO Auto-generated method stub

           

      }

     

}

La descripción no la pasamos como parámetro porque la vamos a escribir manualmente.

Luego con el método putValue() vamos a inicializar nuestros objetos:

    public ActionColor(String nombre, Icon icono, Color color_boton) {

        

      putValue(Action.NAME, nombre);

       

        putValue(Action.SMALL_ICON, icono);

      

        putValue(Action.SHORT_DESCRIPTION, "Rellenar el fondo de color" + nombre);

      

        putValue("color_de_fondo", color_boton);

 

       

    }

Utilizando las constantes de la interfaz Action le damos un valor a nuestros objetos.

En la clase LaminaFuentes dentro del constructor eliminamos lo que hemos añadido antes y vamos a crear las instancias de los objetos oyentes:

class LaminaFuentes extends JPanel{

    public LaminaFuentes() {

       

        ActionColor accionAmarillo = new ActionColor("Amarillo", new ImageIcon("src/event/bola_amarilla.gif"), Color.yellow);

        ActionColor accionAzul = new ActionColor("Azul", new ImageIcon("src/event/bola_azul.gif"), Color.blue);

        ActionColor accionRojo = new ActionColor("Rojo", new ImageIcon("src/event/bola_roja.gif"), Color.red);

 

  }

     

}

Añadimos los botones a la lámina instanciando los objetos:

class LaminaFuentes extends JPanel{

    public LaminaFuentes() {

       

        ActionColor accionAmarillo = new ActionColor("Amarillo", new ImageIcon("src/event/bola_amarilla.gif"), Color.yellow);

        ActionColor accionAzul = new ActionColor("Azul", new ImageIcon("src/event/bola_azul.gif"), Color.blue);

        ActionColor accionRojo = new ActionColor("Rojo", new ImageIcon("src/event/bola_roja.gif"), Color.red);

       

        add(new JButton(accionAmarillo));

        add(new JButton(accionAzul));

        add(new JButton(accionRojo));

 

 

  }

     

}

En el método actionPerformed tenemos que indicar que nos haga la acción, es decir, que nos rellene de color el fondo de la lámina:

      public void actionPerformed(ActionEvent e) {

           

            Color c = getValue("color_de_fondo");

           

      }

Utilizamos el método getValue que va a obtener el valor del objeto, en este caso el color, sin embargo, nos da un error ya que no podemos convertir un objeto en una variable de tipo Color por lo que hay que recurrir al casting:

      public void actionPerformed(ActionEvent e) {

           

            Color c = (Color)getValue("color_de_fondo");

           

      }

Después con el método setBackground rellenar la lámina:

      public void actionPerformed(ActionEvent e) {

           

            Color c = (Color)getValue("color_de_fondo");

           

            setBackground(c);

           

      }

Pero también nos da un error, este método no pertenece a la clase AbstractAction ni a la interfaz Action, sino, a la clase JPanel, como solución hay que convertir la clase ActionColor en una clase interna de la clase JPanel.

Seleccionamos toda la clase ActionColor la cortamos y la pegamos antes de la última llave de cierre posteriormente la encapsulamos con la palabra private.

Si probamos vemos que al pulsar un botón se rellena de color el fondo de la lámina:



Hemos pulsado el botón Azul y se nos ha rellenado el fondo de color azul, lo mismo que si pulsamos los demás botones, si pulsamos el botón Amarillo se rellenará el fondo de color amarillo y si pulsamos el botón rojo el fondo se rellenará de color rojo.

Si nos situamos con el cursor sobre alguno de estos botones:



Nos aparece una breve explicación de lo que hace el botón.

Para acabar nos falta como rellenar el color de fondo de la lámina con una combinación de teclas, esto se hace siguiendo cuatro pasos:

a)    Crear mapa de entrada

Esto quiere decir donde se encuentra el foco para realizar la combinación de teclas. ¿Quién tiene el foco? Aquí se utiliza la clase InputMap y la clase JComponent con el método getInputMap(int condicion)

b)   Crear combinación de teclas.

Cuál va a ser la combinación de teclas. En esta práctica para el color amarillo va a ser Ctrl + y, para el color azul Ctrl + b y para el color rojo Ctrl + r. Se guarda la descripción de las teclas, utilizamos la clase KeyStroke con el método static getKeyStroke(String s).

c)    Asignar combinación de teclas a los objetos

Se utiliza la clase InputMap con el método put(KeyStroke, Object).

d)   Asignar objeto a acción

La clase que se utiliza es ActionMap y el método put(Object, action).

Hasta que no se vea en la práctica y revisemos estos métodos y clases en la API de Java no lo entenderemos mejor. Así que volvemos a la práctica. Dentro del constructor LaminaFuentes() creamos la clase InputMap que lo que nos va a hacer es relacionar un evento y un objeto, este objeto son las teclas del teclado. Utilizamos el método getInputMap que va a tener como parámetro una constante de clase cuando la aplicación tiene el enfoque, esta constante de clase pertenece a la clase JComponent:

InputMap mapaEntrada = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

Este sería el primer paso. El segundo paso con la clase KeyStroke nos vamos a crear un objeto que va a almacenar la combinación de teclas:

 InputMap mapaEntrada = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

        

KeyStroke teclayellow = KeyStroke.getKeyStroke("ctrl Y");

El tercer paso es el objeto que va a tener esa acción, en este caso el botón amarillo que vamos a utilizar el objeto que se ha almacenado en la clase InputMap y el método put que va a tener como parámetro el objeto de la clase KeyStroke que es la combinación de tecla y el segundo parámetro la acción que realiza.

 InputMap mapaEntrada = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

       

        KeyStroke teclayellow = KeyStroke.getKeyStroke("ctrl Y");

       

        mapaEntrada.put(teclayellow, "fondo_amarillo");

El último paso con la clase ActionMap vamos a crear un objeto que va almacenar la acción que se va a realizar que será rellenar de amarillo el fondo de la lámina:

        InputMap mapaEntrada = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

       

        KeyStroke teclayellow = KeyStroke.getKeyStroke("ctrl Y");

       

        mapaEntrada.put(teclayellow, "fondo_amarillo");

       

        ActionMap mapaAccion = getActionMap();

       

        mapaAccion.put("fondo_amarillo", accionAmarillo);            

Ya tendríamos el relleno de la lámina con el color amarillo utilizando una combinación de teclas. Estas mismas líneas de código se pueden reutilizar para el color azul y rojo:

InputMap mapaEntrada = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

       

        KeyStroke teclayellow = KeyStroke.getKeyStroke("ctrl Y");

       

        KeyStroke teclablue = KeyStroke.getKeyStroke("ctrl B");

       

        KeyStroke teclared = KeyStroke.getKeyStroke("ctrl R");

       

        mapaEntrada.put(teclayellow, "fondo_amarillo");

       

        mapaEntrada.put(teclablue, "fondo_azul");

       

        mapaEntrada.put(teclared, "fondo_rojo");

       

        ActionMap mapaAccion = getActionMap();

       

        mapaAccion.put("fondo_amarillo", accionAmarillo);

       

        mapaAccion.put("fondo_azul", accionAzul);

       

        mapaAccion.put("fondo_rojo", accionRojo);

Y ya estaría la aplicación terminada. Con cualquier duda me lo podéis hacer llegar a través de los comentarios del blog. Hasta pronto!

5.5 EVENTOS DE FOCO << >> 5.7EVENTOS MÚLTIPLES OYENTES



No hay comentarios:

Publicar un comentario