JTextField que solo admite digitos

De ChuWiki

Para conseguir que un JTextField sólo admita números (o en general controlar su entrada para que cumpla ciertas características), tenemos muchas opciones disponibles.

Podemos hacer dos grandes grupos de soluciones. El primero son las soluciones que permiten escribir cualquier cosa, pero luego protestan al intentar coger el número. El segundo son las que directamente NO dejan escribir algo no válido.


Contenido

Admiten cualquier cosa y protestan luego

JFormattedTextField

Una opción es usar un JFormattedTextField en vez de un JTextField. Con esto, el código es tan tonto como esto

JFormattedTextField textField1 = new JFormattedTextField (new Integer(3));

o bien

JFormattedTextField textField2 = new JFormattedTextField ();
textField2.setValue(new Integer(3));

y cuando queramos leer, sólo tenemos que hacer

Integer valor = textField1.getValue();

Si el usuario escribe letras, entonces el método getValue() nos devolverá el último valor bueno conocido y el JFormattedTextField modificará su contenido para mostrar ese último valor.

Añadir un FocusLost

Añadiendo un FocusListener al JTextField, nos enteraremos de cuando se pierde el foco. Podemos entonces verificar si la entrada nos gusta o no.

textField.addFocusListener (new FocusListener()
{
   public void focusLost (FocusEvent e)
   {
      String cadena = textField.getText();
      // Aquí verificamos si la cadena es correcta.
   }
   ...
});


Añadir un InputVerifier

El InputVerifier es una característica un poco olvidada de Java. Todos los componentes de Swing colaboran entre ellos a la hora de pasarse el foco de unos a otros. Si un componente gana el foco, primero le pregunta al componente que lo pierde (y en concreto a su InputVerifier) si se puede hacer la trasnmisión del foco.

De esta forma, por ejemplo, si escribimos algo en el JTextField y vamos a pulsar un JButton, el JButton antes de ganar el foco preguntará el InputVerifier del JTextField si se puede cambiar el foco del JTextField al JButton. Este es el momento que tiene el JTextField para verificar si su entrada es o no correcta y negarse a perder el foco hasta que lo sea. El resultado es que podemos escribir cosas incorrectas, pero no podremos salir del JTextField hasta que la entrada sea correcta.

El código puede ser como este

textField.setInputVerifier(new InputVerifier()
{
   public boolean verify(JComponent input) {
      JTextField tf = (JTextField) input;
      String cadena = tf.getText();
      // Aqui verificamos si cadena es correcta y devolvemos
      if (cadenaEsCorrecta) return true;
      else return false;
});


No admiten cualquier cosa

Si queremos ser más restrictivos y no queremos dejar al usuario escribir cualquier cosa, tenemos varios métodos disponibles


Usar una máscara con el JFormattedTextField

Si usamos un JFormattedTextField con máscara, entonces no podremos escribir nada fuera de esa máscara. Este JFormattedTextField se crea así

try
{
   MaskFormatter mascara = new MaskFormatter("##.##");
   JFormattedTextField textField = new JFormattedTextField(mascara);
   textField.setValue(new Float("12.34"));
}
catch (Exception e)
{
   ...
}

El manejo ahora es igual que en el caso anterior, usando

Double valor =  textField.getValue();

Capturar el teclado

Otra opción es capturar el teclado y verificar cada pulsación de tecla si es o no correcta

JTextField textField = new JTextField(10);
textField.addKeyListener(new KeyAdapter()
{
   public void keyTyped(KeyEvent e)
   {
      char caracter = e.getKeyChar();

      // Verificar si la tecla pulsada no es un digito
      if(((caracter < '0') ||
         (caracter > '9')) &&
         (caracter != KeyEvent.VK_BACK_SPACE))
      {
         e.consume();  // ignorar el evento de teclado
      }
   }
});

Esta opción está bastante extendida, sin embargo es costosa de hacer bien. Entre las teclas admitidas hemos puesto la de VK_BACK_SPACE, puesto que si no esa tecla también se ignora y no se puede borrar. Aunque no lo he probado, habría posiblemente también que admitir teclas como Ctrl-C y Ctrl-V para permitir copy-paste, quizás el <enter> para que se dispare el ActionEvent, etc.

Si no somos cuidadosos, tendremos un JTextField que no admite otra cosa que no sea números, pero tampoco muchas de las funcionalidades estandard de una caja de texto.

Modificar el Document

Finalmente, otra opción es crearnos un Document y añadirlo. En el Document tenemos que hacer algo parecido al KeyListener, pero a un nivel más alto. No debemos preocuparnos de las teclas una a una, sino sólo del cacho de texto completo que se quiere añadir, borrar, etc.

La forma más fácil de contruir el Document es heredando de PlainDocument y sobreescribiendo el método que nos interesa.

class LimitadorCaracteres extends PlainDocument
{
   /**
    * Método al que llama el editor cada vez que se intenta insertar caracteres.
    * Sólo debemos verificar arg1, que es la cadena que se quiere insertar en el JTextField
    */
   public void insertString(int arg0, String arg1, AttributeSet arg2) throws BadLocationException
   {
       for (int i=0;i<arg1.length();i++)
          // si no es digit, volvemos
          if (!Character.isDigit(arg1.charAt(i)))
             return;

       // Si todos son digit, insertamos el texto en el JTextField
       super.insertString(arg0, arg1, arg2);
   }
} 

y luego, hay poner este Document en el JTextField

textField.setDocument (new LimitadorCaracteres());

Herramientas personales

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner http://www.chuidiang.com/chuwiki