Hola a todos, ¿qué tal? Cuando hablamos de
foco nos referimos al objeto que esté activo en ese momento, ventanas, botones,
carpetas, etc. Por ejemplo, si tenemos dos ventanas abiertas en el escritorio
una de ellas es la que estará activa, es la que tiene el foco. Si entramos
dentro de una carpeta donde tiene varias subcarpetas y archivos, si
seleccionamos una de las subcarpetas la que tiene el foco es la que está
seleccionada. Lo mismo ocurre con los formularios, un formulario con varios
campos de texto, solo uno de ellos será el que tenga el foco, es decir, donde
tengamos puesto el cursor, es el campo de texto activo el que tiene el foco.
Para trabajar con eventos de foco utilizamos la interface FocusListener la cual tiene dos métodos que tenemos que declarar de forma obligada, aunque también contamos con la clase FocusAdapter por si no es necesario utilizar estos dos métodos y solo queremos utilizar uno.
El método FocusGained se
utiliza para los objetos que tienen el foco y el método FocusLost son
para los objetos que pierden o no tienen el foco.
Para ver con detenimiento los eventos de foco
vamos a crear una aplicación con dos campos de texto, aunque no hemos adentrado
todavía en los diferentes componentes swing que los veremos de forma más
avanzada en otro apartado, en esta ocasión sí que vamos a ver el componente
campo de texto aunque sea por encima, solo para este ejemplo.
La aplicación va a tener dos campos de texto
uno debajo del otro y en el momento que uno de los campos de texto pierda el
foco se desencadene una acción. Nos creamos un archivo llamado EventosFoco con el siguiente código:
package lay;
import
java.awt.Graphics;
import
javax.swing.JFrame;
import
javax.swing.JPanel;
public class EventosFoco {
public static void main(String[] args) {
MarcoFoco mimarco=new MarcoFoco();
mimarco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class MarcoFoco
extends JFrame{
public MarcoFoco() {
setVisible(true);
setBounds(700, 300, 600, 450);
add (new LaminaFoco());
}
}
class LaminaFoco
extends JPanel {
public void
paintComponent(Graphics g) {
super.paintComponent(g);
}
}
Lo primero que vamos a hacer es añadir estos
dos campos de texto a la lámina e invalidar el layout, el layout lo
veremos más adelante es la disposición que tienen los elementos dentro de una
ventana, es decir, cuando colocamos objetos en una ventana, botones, campos de
texto… Java los posiciona de forma automática. Si queremos que no los
posicione, que nosotros seamos los que coloquemos el objeto tenemos que
invalidar es el layout y esto se hace con el método setLayout y
le pasamos como parámetro null:
class LaminaFoco
extends JPanel {
public void
paintComponent(Graphics g) {
super.paintComponent(g);
setLayout(null);
}
}
Para añadir los dos campos de texto tenemos
que utilizar la clase JTextField, consultad en la API de Java para tener más
información sobre ella.
Tiene varios constructores el que vamos a
utilizar es el más sencillo y lo que hace es construir un nuevo campo de texto.
En la clase LaminaFoco vamos a crearnos dos
variables de clase JTextField fuera del método:
class LaminaFoco
extends JPanel {
public void paintComponent(Graphics
g) {
super.paintComponent(g);
setLayout(null);
}
JTextField cuadro1;
JTextField cuadro2;
}
Ahora dentro del método instanciamos estas
dos variables:
class LaminaFoco
extends JPanel {
public void
paintComponent(Graphics g) {
super.paintComponent(g);
setLayout(null);
cuadro1 = new
JTextField();
cuadro2 = new
JTextField();
}
JTextField cuadro1;
JTextField cuadro2;
}
Como hemos invalidado el layout tenemos que
posicionar donde queramos los campos de texto para ello utilizamos el
método setBounds:
class LaminaFoco
extends JPanel {
public void
paintComponent(Graphics g) {
super.paintComponent(g);
setLayout(null);
cuadro1 = new JTextField();
cuadro2 = new JTextField();
cuadro1.setBounds(120, 10, 150,
20);
cuadro2.setBounds(120, 50, 150,
20);
}
JTextField cuadro1;
JTextField cuadro2;
}
Finalmente añadimos los campos de texto a la
lámina:
class LaminaFoco
extends JPanel {
public void
paintComponent(Graphics g) {
super.paintComponent(g);
setLayout(null);
cuadro1 = new JTextField();
cuadro2 = new JTextField();
cuadro1.setBounds(120,
10, 150, 20);
cuadro2.setBounds(120,
50, 150, 20);
add(cuadro1);
add(cuadro2);
}
JTextField cuadro1;
JTextField cuadro2;
}
Probamos:
Lo que queremos es escribir una dirección
mail en el primer campo de texto y al pasar al segundo campo de texto, es
decir, cuando el primer campo pierda el foco si la dirección de correo no está
bien escrita nos aparezca un mensaje en la consola indicando que no está bien
escrita. ¿Cómo va a saber la aplicación que está mal escrita? Porque no tiene
el símbolo del arroba @
Los cuadros de texto ya están creados y lo
que necesitamos es el objeto fuente del evento y el oyente. Si creamos la clase
después de la clase LaminaFoco:
class LanzaFoco implements FocusListener{
@Override
public void
focusGained(FocusEvent e) {
// TODO
Auto-generated method stub
}
@Override
public void
focusLost(FocusEvent e) {
// TODO
Auto-generated method stub
}
}
En el momento que programe uno de los métodos
voy a necesitar uno de los objetos que se han declarado en la clase
LaminaFoco, esto es un problema ya que están declarados en clases diferentes,
en este caso, hemos de recurrir a las clases internas, tenemos que hacer que la
clase LanzaFoco sea una clase interna de la clase LaminaFoco. Por lo que
seleccionamos todo el código referente a la clase LanzaFoco la cortamos y la
pegamos dentro de la clase LaminaFoco:
class LaminaFoco
extends JPanel {
public void
paintComponent(Graphics g) {
super.paintComponent(g);
setLayout(null);
cuadro1 = new JTextField();
cuadro2 = new JTextField();
cuadro1.setBounds(120, 10, 150, 20);
cuadro2.setBounds(120, 50, 150, 20);
add(cuadro1);
add(cuadro2);
}
private class LanzaFoco
implements FocusListener{
@Override
public void
focusGained(FocusEvent e) {
// TODO
Auto-generated method stub
}
@Override
public void
focusLost(FocusEvent e) {
// TODO
Auto-generated method stub
}
}
JTextField cuadro1;
JTextField cuadro2;
}
Esto nos va a permitir acceder a los objetos cuadro1 y cuadro2.
Una vez hecho esto el siguiente paso será
determinar cuál de los dos campos de texto es el que va a estar a la escucha,
el componente que va a estar a la escucha es el primer cuadro. Creamos una
instancia de la clase oyente:
class LaminaFoco
extends JPanel {
public void
paintComponent(Graphics g) {
super.paintComponent(g);
setLayout(null);
cuadro1 = new JTextField();
cuadro2 = new JTextField();
cuadro1.setBounds(120, 10, 150, 20);
cuadro2.setBounds(120, 50, 150, 20);
add(cuadro1);
add(cuadro2);
LanzaFoco elFoco = new LanzaFoco();
cuadro1.addFocusListener(elFoco);
}
Tenemos que programar en el método que pierde
el foco focusLost un mensaje en
consola para que nos lo imprima cuando el primer campo de texto pierda el foco:
public void
focusLost(FocusEvent e) {
System.out.println("Has
perdido el foco");
}
Probamos:
Escribimos algo en el primer campo de texto y
cuando pulsemos tabulador para pasar al segundo campo de texto nos imprime en
consola el mensaje que hemos programado en el método.
Sin embargo, lo que queremos es que nos
indique si en el primer campo de texto introducimos una cuenta e-mail cuando
pasemos al siguiente campo de texto nos salga un mensaje en consola indicando
si es correcta la dirección o no.
Eliminamos el System.out del
método focusLost y nos creamos una variable de tipo String que
va a almacenar la información que escribamos en el campo de texto utilizamos el
método getText() lo que hace es capturar el texto.
public void focusLost(FocusEvent
e) {
String email = cuadro1.getText();
}
A continuación, vamos a crear una variable de
tipo boolean que nos indique si es correcto o no la dirección, mediante un for
vamos a recorrer el texto introducido en el campo de texto, mediante una
condicional le vamos a indicar que si tiene un @ está bien escrita y si no
tiene el @ no es correcta, el código sería el siguiente:
public void
focusLost(FocusEvent e) {
String email = cuadro1.getText();
boolean comprobacion = false;
for(int i=0; i<email.length(); i++) {
if (email.charAt(i)=='@') {
comprobacion=true;
}
}
if(comprobacion) {
System.out.println("Correcto!");
}else {
System.out.println("La
dirección introducida es incorrecta");
}
}
}
Vamos a ver otro ejemplo, una aplicación con dos
ventanas y una de ellas cuando tenga el foco que realice alguna acción.
Por lo pronto nos vamos a crear una clase con el
siguiente código:
package lay;
public class FocoVentana {
public static void main(String[] args) {
// TODO
Auto-generated method stub
}
}
Esta clase va a heredar de JFrame:
package lay;
import
javax.swing.JFrame;
public class FocoVentana
extends JFrame {
public static void main(String[] args) {
// TODO
Auto-generated method stub
}
}
Implementamos la interfaz WindowFocusListener
package lay;
import
java.awt.event.WindowFocusListener;
import
javax.swing.JFrame;
public class FocoVentana extends JFrame implements
WindowFocusListener {
public static void main(String[] args) {
// TODO
Auto-generated method stub
}
}
Tenemos que declarar los métodos de forma obligatoria:
package lay;
import
java.awt.event.WindowEvent;
import
java.awt.event.WindowFocusListener;
import
javax.swing.JFrame;
public class FocoVentana extends JFrame implements
WindowFocusListener {
public static void main(String[] args) {
// TODO
Auto-generated method stub
}
@Override
public void
windowGainedFocus(WindowEvent e) {
// TODO
Auto-generated method stub
}
@Override
public void
windowLostFocus(WindowEvent e) {
// TODO
Auto-generated method stub
}
}
Creamos otro método más que es donde se crearan los
marcos y antes de ello declaráramos dos
variables que van a ser las ventanas:
FocoVentana marco1;
FocoVentana marco2;
En el nuevo método escribimos lo siguiente:
public void iniciar() {
marco1 = new FocoVentana();
marco2 = new FocoVentana();
marco1.setVisible(true);
marco2.setVisible(true);
marco1.setBounds(300, 100, 600, 350);
marco2.setBounds(1200, 100, 600, 350);
}
Indicamos lo que tiene que hacer cuando cerramos estas
ventanas:
marco1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
marco2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Ahora tenemos que poner estos marcos a la escucha del
evento correspondiente, tenemos que pasar como parámetro la clase oyente pero
como es la propia clase utilizamos la palabra this:
marco1.addWindowFocusListener(this);
marco2.addWindowFocusListener(this);
Y en la función principal, en el método main nos
creamos un objeto de la clase:
public static void main(String[] args) {
FocoVentana
miven = new FocoVentana();
miven.iniciar();
}
Vamos a hacer que la ventana que tenga el foco
aparezca en la barra de título “Tengo el foco” cuando pierda el foco el
título desaparezca y si el foco lo tiene la otra ventana que aparezca el título
en la barra de título. En el método windowGainedFocus vamos a
programar mediante un condicional y utilizando el método e.getSource() que
detecta el origen del evento producido que cuando ese campo de texto que tiene
el foco aparezca un título en la barra de título:
public void
windowGainedFocus(WindowEvent e) {
if(e.getSource()==marco1) {
marco1.setTitle("Tengo el
foco!");
}else {
marco2.setTitle("Tengo el
foco!");
}
}
En el método windowLostFocus() tenemos
que indicarle que tiene que hacer la ventana cuando no tenga el foco, lo que
queremos es que le desaparezca el título, por lo que es el mismo código
anterior pero en el título escribimos una cadena vacía:
public void
windowLostFocus(WindowEvent e) {
if(e.getSource()==marco1) {
marco1.setTitle(" ");
}else {
marco2.setTitle(" ");
}
}
Y ya tenemos nuestra aplicación acabada. Hasta pronto!
5.4 EVENTOS DE RATÓN << >> 5.6 EVENTOSMÚLTIPLES FUENTES
No hay comentarios:
Publicar un comentario