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