Verificación de la información que se introduce en un control de edición

prev.gif (997 bytes)chapter.gif (1105 bytes)home.gif (1232 bytes)next.gif (1211 bytes)

Sucesos (events)

Introducción

El control de edición

Verificación de los datos mientras se introducen

Verificación después de introducir los datos


Introducción

La mayoría de los applets disponen de controles de edición en los que se introducen datos para su procesamiento por el programa. La verificación de los datos que se introducen en los controles de edición tiene gran importancia para el correcto funcionamiento del programa.

La verificación del dato, se puede realizar mientras se teclean los caracteres o bien después de haber introducido dicho dato en el control de edición. El primer caso, se emplea para eliminar los caracteres no deseados que tecleamos sin darnos cuenta, por ejemplo letras cuando se requieren caracteres numéricos o viceversa. El segundo caso, se emplea por ejemplo, para verificar que la cantidad introducida está dentro de un intervalo apropiado.

 

El control de edición

Se crea el control de edición  llamanado a uno de sus constructores

	TextField textEntero = new TextField();

Se establece el tamaño del control mediante setColums

        textEntero.setColumns(4);

Se puede habilitar o inhabilitar el control de edición, es decir, puede hacerse de lectura/escritura o de sólo lectura.

        textEntero.setEditable(false);

Para poner texto en el control de edición, se llama a setText.

	textEntero.setText("3");

Para obtener el texto del control de edición, se emplea getText.

	String texto=textEntero.getText();

 

Verificación de los datos mientras se introducen

disco.gif (1035 bytes)edicion1: EdicionApplet1.java

Propósito

Filtrar los caracteres que se introducen en el control de modo que solamente se muestren caracteres no numéricos.

Diseño

Crear un applet y situar sobre el applet en el modo diseño (pestaña Design) un control etiqueta (Label) y un control de edición (TextField).

Cambiar sus propiedades en sus respectivas hojas de propiedades

Establecer FlowLayout como gestor de diseño del applet

Respuesta a las acciones del usuario

Para gestionar los sucesos procedentes del teclado que se producen en un componente, se han de seguir los siguientes pasos.

public interface KeyListener extends EventListener {
    public void keyTyped(KeyEvent e);
    public void keyPressed(KeyEvent e);
    public void keyReleased(KeyEvent e);
}

En vez de implementar el interface KeyListener, tenemos la opción de crear una clase que derive de la clase KeyAdapter (véase Listeners y adapters) y redefinir algunas de sus funciones miembro por ejemplo, keyPressed.

class ValidaCaracter extends KeyAdapter{
  public void keyPressed(KeyEvent ev){
    int codigo=ev.getKeyCode();
    if(codigo>=KeyEvent.VK_0 && codigo<=KeyEvent.VK_9){
        ev.consume();
    }
 }
}

El objeto ev de la clase KeyEvent nos suministra código de la tecla que se ha pulsado que se extrae mediante su función miembro getKeyCode o el carácter tecleado mediante getKeyChar. Si dicho código corresponde a una tecla numérica, el suceso se consume, conlcuye su procesamiento, y por tanto, no se muestra en el control de edición.

     int codigo=ev.getKeyCode();
     if(codigo>=KeyEvent.VK_0 && codigo<=KeyEvent.VK_9){
        ev.consume();
    }

Otra forma equivalente sería la siguiente

    char tecla=ev.getKeyChar();
    if(tecla>='0' && tecla<='9'){
        ev.consume();
    }

Asociamos mediante addKeyListener, el control de edición textIntro en el que ocurren los sucesos relacionados con el teclado, con un objeto de la clase ValidaCaracter que maneja dichos sucesos.

	ValidaCaracter valChar=new ValidaCaracter();
        textIntro.addKeyListener(valChar);        

o bien, en una sóla línea

        textIntro.addKeyListener(new ValidaCaracter());        

De un modo análogo, se podría definir una clase que filtrase los caracteres numéricos.

El código completo de este ejemplo, es el siguiente

package edicion1;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class EdicionApplet1 extends Applet {
    TextField textIntro = new TextField();
    Label label1 = new Label();
    FlowLayout flowLayout1 = new FlowLayout();

    public void init() {
        textIntro.setColumns(10);
        label1.setText("Introducir carcateres NO numéricos");
       	this.setLayout(flowLayout1);
       	this.add(label1, null);
        this.add(textIntro, null);
        ValidaCaracter valChar=new ValidaCaracter();
        textIntro.addKeyListener(valChar);
   }
}

 class ValidaCaracter extends KeyAdapter{
  public void keyPressed(KeyEvent ev){
    int codigo=ev.getKeyCode();
    if(codigo>=KeyEvent.VK_0 && codigo<=KeyEvent.VK_9){
        ev.consume();
    }
 }
}

 

Verificación después de introducir los datos

disco.gif (1035 bytes)edicion2: EdicionApplet2.java

Propósito

El propósito del programa es verificar la información que ha introducido el usuario en los controles de edición. En el primer control de edición se espera que introduzca un número entero, y en el segundo un número decimal. Si se introducen caracteres no numéricos, o una coma como separador de la parte entera y decimal el control de edición recupera el foco, para que el usuario corrija los errores.

Nota: Es posible que el applet no funcione en el navegador Internet Explorer 4.0 de Microsoft como se describe, pero funciona correctamente en el AppletViewer del IDE JBuilder 2.0.

Diseño

Crear un applet, en el modo diseño (pestaña Design), situar tres paneles, uno en la parte superior, otro en el centro y otro en la parte inferior, tal como se indica en la figura.

edicion2.gif (2905 bytes)

Cambiar las propiedades de cada uno de los controles en sus respectivas hojas de propiedades.

Establecer FlowLayout como gestor de diseño de cada uno de los paneles

Establecer BorderLayout como gestor de diseño del applet, de modo que el panel superior quede al norte (NORTH), el central en el centro (CENTER) y el inferior en el sur (SOUTH).

Nota acerca de los paneles:

Cuando se coloca un panel AWT sobre el applet en el modo diseño, se hace invisible para el programador. Este inconveniente se puede resolver de dos formas distintas:

  1. Cambiar el color del fondo del panel de modo que se haga visible. Cuando el diseño este completo, se restaura el color por defecto.
  1. Emplear paneles BevelPanel de la paleta JBCL Containers, estos paneles son visbles ya que tienen un borde (bevel). Cuando el diseño esté terminado reemplazamos  BevelPanel por Panel en el código fuente, mediante Search/Replace o el botón correspondiente de la barra de herramientas, y eliminamos las sentencias import que hacen referencia a los controles propios de Borland.
import borland.jbcl.control.*;
import borland.jbcl.layout.*;

Respuesta a las acciones del usuario

Cuando un control de edición tiene el foco podemos introducir caracteres en dicho control, cuando pulsamos la tecla del tabulador, el foco pasa a otro control, y así sucesivamente.

Para gestionar los sucesos asociados al cambio de foco, se han de seguir los siguientes pasos.

public interface FocusListener extends EventListener {
    public void focusGained(FocusEvent e);
    public void focusLost(FocusEvent e);
}

En vez de implemantar el interface FocusListener, tenemos la opción de crear una clase que derive de la clase FocusAdapter (véase Listeners y adapters) y redefinir algunas de sus funciones miembro por ejemplo focusLost.

Podemos verificar el dato introducido en un control de edición cuando dicho control pierde el foco.Vamos a ver dos ejemplos: verificar que se introduce un número entero y verificar que se introduce un número decimal.

 

Número entero

En primer lugar, creamos una clase que deriva de FocusAdapter, (véase Listeners y adapters) y redefinimos la  función miembro focusLost en la que estamos interesados.

class ValidaInt extends FocusAdapter{
     public void focusLost(FocusEvent ev){
          TextField tEntrada=(TextField)(ev.getSource());
          try{
               Integer.parseInt(tEntrada.getText().trim());
          }catch(NumberFormatException e){
               tEntrada.requestFocus();
               tEntrada.selectAll();
          }
     }
}

El objeto ev de la clase FocusEvent guarda toda la información relativa al suceso, y en particular, la fuente o el control que lo ha generado, dicha información se extrae mediante la función getSource.

Una vez que se ha obtenido el control de edición tEntrada que ha generado el suceso, se obtiene el texto, un objeto de la clase String, que se ha introducido en dicho control mediante la función getText.

Posteriormente, se eliminan los espacios en blanco al principio y al final mediante la función trim, y se convierte el string en un número entero mediante la función parseInt.

Si el proceso de conversión falla, por que se han introducido caracteres que no son números, se produce un excepción del tipo NumberFormatException. En este caso, el control de edición vuelve a tomar el foco requestFocus, y se selecciona todos los caracteres introducidos para que puedan ser borrados de una sola vez pulsando la tecla RETROCESO.

	tEntrada.requestFocus();
        tEntrada.selectAll();

Asociamos, mediante addFocusListener, el control de edición textEntero en el que ocurren los sucesos relacionados con el teclado con un objeto de la clase ValidaInt que registra dichos sucesos.

        ValidaInt valInt=new ValidaInt();
        textEntero.addFocusListener(valInt);

o bien, en una sóla línea de código

        textEntero.addFocusListener(new ValidaInt());

 

Número real

Lo mismo que hemos hecho para un número entero se puede repetir para un número real. Esto es importante, ya que tenemos la costumbre de poner una coma como carácter separador de la parte entera y de la parte decimal, lo que no es admitido por el programa. Por tanto, para su buen comportamiento debemos de notificar esta circustancia al usuario.

class ValidaDouble extends FocusAdapter{
     public void focusLost(FocusEvent ev){
          TextField tEntrada=(TextField)(ev.getSource());
          try{
               Double.valueOf(tEntrada.getText()).doubleValue();
          }catch(NumberFormatException e){
               tEntrada.requestFocus();
               tEntrada.selectAll();
          }
     }
}

Asociamos, mediante addFocusListener, el control de edición textDecimal en el que ocurren los sucesos relacionados con el teclado con un objeto de la clase ValidaDecimal que registra dichos sucesos.

        ValidaDouble valDouble=new ValidaDouble();
        textDecimal.addFocusListener(valDouble);

o bien, en una sóla línea de código

        textDecimal.addFocusListener(new ValidaDouble());

El código fuente completo de este ejemplo, es el siguiente

package edicion2;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class EdicionApplet2 extends Applet {
    TextField textEntero = new TextField();
    TextField textDecimal = new TextField();
    Button btnAceptar = new Button();
    Panel bevelPanel1 = new Panel();
    Panel bevelPanel2 = new Panel();
    Panel bevelPanel3 = new Panel();
    Label label1 = new Label();
    Label label2 = new Label();
    FlowLayout flowLayout1 = new FlowLayout();
    FlowLayout flowLayout2 = new FlowLayout();
    FlowLayout flowLayout3 = new FlowLayout();
    BorderLayout borderLayout1 = new BorderLayout();

    public void init() {
        this.setLayout(borderLayout1);
        btnAceptar.setLabel("Aceptar");
        bevelPanel3.setLayout(flowLayout3);
        bevelPanel2.setLayout(flowLayout2);
        bevelPanel1.setLayout(flowLayout1);
//número entero
        textEntero.setText("3");
        textEntero.setColumns(4);
        label1.setText("Introduce un número entero");
        ValidaInt valInt=new ValidaInt();
        textEntero.addFocusListener(valInt);

//número decimal
        textDecimal.setText("1.3");
        textDecimal.setColumns(4);
        label2.setText("Introduce un número decimal");
        ValidaDouble valDouble=new ValidaDouble();
        textDecimal.addFocusListener(valDouble);

        this.add(bevelPanel1, BorderLayout.NORTH);
        bevelPanel1.add(label1, null);
        bevelPanel1.add(textEntero, null);
        this.add(bevelPanel2, BorderLayout.CENTER);
        bevelPanel2.add(label2, null);
        bevelPanel2.add(textDecimal, null);
        this.add(bevelPanel3, BorderLayout.SOUTH);
        bevelPanel3.add(btnAceptar, null);
    }
}

class ValidaDouble extends FocusAdapter{
     public void focusLost(FocusEvent ev){
          TextField tEntrada=(TextField)(ev.getSource());
          try{
               Double.valueOf(tEntrada.getText()).doubleValue();
          }catch(NumberFormatException e){
               tEntrada.requestFocus();
               tEntrada.selectAll();
          }
     }
}

class ValidaInt extends FocusAdapter{
     public void focusLost(FocusEvent ev){
          TextField tEntrada=(TextField)(ev.getSource());
          try{
               Integer.parseInt(tEntrada.getText().trim());
          }catch(NumberFormatException e){
               tEntrada.requestFocus();
               tEntrada.selectAll();
          }
     }
}