5.5 EVENTOS DE FOCO

 

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