Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

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

Ejemplos de uso del JFormattedTextField

El JFormattedTextField es un componente java un paso más evolucionado que un JTextField normalito. El JTextField permite al usuario meter texto. Cuando desde nuestro código le pedimos el contenido, nos devuelve el texto introducido por el usuario como String. Cuando desde código le decimos lo que queremos que muestre, debemos pasarle un String. El JTextField, además, no hace ningún tipo de comprobación sobre el texto.

El JFormattedTextField da un paso más allá. Aunque el usuario mete un texto, el JFormattedTextField lo convierte a la clase que nosotros queramos (un Integer, Float, Date o incluso una clase nuestra propia). Cuando queramos pasarle algo, le podemos pasar directamente cualquiera de estas clases y él se encarga de la conversión a texto para mostrar.

JFormattedTextField para editar Integer

Para editar cualquier tipo básico de java, estilo Integer, Float, Double, Date, etc, basta con llamar al método setValue() del JFormattedTextField pasándole uno de estos tipos de datos, o bien pasárselo en el constructor.

Por ejemplo, para Integer, nos bastaría con cualquiera de los dos casos siguientes:

JFormattedTextField textField1 = new JFormattedTextField (new Integer(3));
// o bien ....
JFormattedTextField textField2 = new JFormattedTextField ();
textField2.setValue(new Integer(3));

Con esto ya tenemos un editor que nos permite recoger Integer directamente cuando el usuario lo edite

Integer valor = textField1.getValue();

Supongamos que el usuario escribe algo en el JFormattedTextField y luego pincha con el ratón en otros sitio (se dice que el JFormattedTextField pierde el foco), por ejemplo, en un botón de "Aceptar" los cambios introducidos. En el momento que el JFormattedTextField pierde el foco, comprueba el texto escrito por el usuario. Si es correcto, lo guarda de forma que el método getValue() nos devolverá el nuevo valor. Si es incorrecto, pondrá automáticamente el último valor bueno, deshaciendo el cambio hecho por el usuario.

Si no te interesa cambiar ese comportamiento, puedes pasar al siguiente punto. Si quieres cambiarlo, sigue leyendo.

Este comportamiento puede cambiarse con el método setFocusLostBehavior(), al que podemos pasar varios valores:

Puedes ver estos cuatro casos funcionando en unos applets de ejemplo. También puedes descargarte los fuentes de los mismos.

JFormattedTextField para editar nuestra propia clase

Podemos usar la forma indicada en el punto anterior con cualquier clase básica de java (Integer, Float, Date, etc). Si queremos que el JFormattedTextField nos acepte y devuelva una clase nuestra propia, debemos hacer un poco más de código.

Vamos primero a definir nuestra propia clase. Por ejemplo, una clase Mayuscula que representa una cadena de texto siempre en mayúsculas. Le ponemos un constructor que admita un String para convertirlo a mayúsculas y un método toString() para obtener la cadena en mayúsculas. La clase puede ser como esta

/**Representa una cadena en mayúsculas */
class Mayusculas
{
    /** La cadena en mayúsculas */
    private String valor="";

    /** Pasa a mayúsculas la cadena que se le pasa y la guarda */
    public Mayusculas(String cadena)
    {
        valor = cadena.toUpperCase();
    }

    /** Devuelve la cadena en mayúsculas */
    public String toString()
    {
        return valor;
    }
}

Para que el JFormattedTextField nos acepte esto en sus métodos setValue() y getValue(), tiene que saber la forma de convertir esto a un texto que se muestre en el editor y la forma de convertir el texto recogido del editor y convertirlo a esta clase.

Las clases que realizan este tipo de conversiones para el JFormattedTextField heredan de JFormattedTextField.AbstractFormatter, una clase interna del JFormattedTextField. Si queremos usar nuestra clase Mayuscula, debemos hacer una clase hija de JFormattedTextField.AbstractFormatter y definir los dos métodos abstractos que tiene que son, precisamente, los de convertir de clase a String y de String a clase.

/** Clase que sabe convertir Mayuscula a texto para presentar en el editor y
       de texto recogido del editor obtener una clase Mayúscula
*/

class Formateador extends JFormattedTextField.AbstractFormatter
{
    /** Se le pasa el texto del editor y debe devolver una clase Mayuscula */
    public Object stringToValue(String text) throws ParseException
    {
        return new Mayusculas(text);
    }

    /** Se le pasa una clase Mayuscula o null y devuelve la cadena para poner en
           el editor */

    public String valueToString(Object value) throws ParseException
    {
        if (value==null)
            return ("");
        return value.toString();
    }
}

Bien, ya tenemos todo lo necesario construido. Ahora solo hay que instanciar el JFormattedTextField pasándole en el constructor nuestra clase Formateador y con setValue() darle un primer valor válido para evitar problemas.

JFormattedTextField textField = new JFormattedTextField(new Formateador());
textField.setValue(new Mayusculas("hola"));

El método getValue() nos devolverá una clase Mayusculas y a través de setValue() podemos pasarle una clase Mayusculas sin problemas.

Puedes ver un Applet con este editor funcionando y descargarte sus fuentes.

JFormattedTextField con máscara para Float

Existen varios JFormattedTextField.AbstractFormatter además de los que podamos hacernos nosotros. Uno de los más conocidos es el MaskFormatter. Este formateador restringe el texto válido incluso mientras lo estamos tecleando. Al instanciar el MaskFormatter le damos un "patrón" sobre cómo queremos que sea el texto. Una vez configurado todo, el usuario no podrá escribir en el FormattedTextField nada que se salga de ese "patrón". Veamos con un ejemplo qué quiero decir.

Supongamos que quiero un editor que me permita escribir un número con dos cifras enteras y dos decimales. No queremos que el usuario escriba algo que no sea un número y no queremos que escriba ni más ni menos de las cifras de las indicadas. El editor debe admitir y devolvernos con setValue() y getValue() un Float.

Para conseguir esto, basta instanciar un MaskFormatter y pasárselo al JFormattedTextField en el constructor. Para evitar problemas, le damos un valor válido inicial válido al editor. El new MaskFormatter lanza una excepción, así que debemos capturarla.

try
{
    /* El "patrón" para el editor. Las # representan cifras. En la API puedes ver más. Ojo con el punto decimal, según el idioma puede ser una coma.*/
    MaskFormatter mascara = new MaskFormatter("##.##");
    // Se construye el JFormattedTextField pasándole la máscara
    JFormattedTextField textField = new JFormattedTextField(mascara);
    // Se da un valor inicial válido para evitar problemas
    textField.setValue(new Float("12.34"));
}
catch (...)

Ya está listo. Nuestro editor sólo admite números de dos cifras enteras y dos decimales y no nos deja escribir otra cosa. Los métodos getValue() y setValue() devuelven y admiten Floats.

Podemos usar el MaskFormatter con cualquier tipo de dato que:

Puedes ver un Applet funcionando con este editor y descargarte sus fuentes.

JFormattedTextField con máscara para nuestra propia clase.

El MaskFormatter nos vale también para la clase Date. El problema es que debemos restringirnos a los formatos de texto que entiende Date en su constructor con String, que no son precisamente bonitos ni cómodos para introducir un usuario.

Si queremos usar MaskFormatter con un formato distinto para Date o bien usar MaskFormatter con una clase nuestra, debemos hacer algo parecido a lo que hicimos para poder usar nuestras propias clases, pero heredando de MaskFormatter en vez de heredar de JFormattedTextField.AbstractFormatter.

Por ejemplo, supongamos que queremos un editor de Fecha hora en este formato "dd/mm/yy hh:mm:ss" y que no queremos que nos dejen escribir nada incorrecto.

Tenemos que hacernos nuestro propio MaskFormatter heredando del original y redefiniendo los métodos de conversion de Date a String y de String a Date

/** Mascara para fecha/hora a nuestro gusto */
class FormatoFecha extends MaskFormatter
{
    /** Se construye con el patrón deseado */
    public FormatoFecha() throws ParseException
    {
        // Las # son cifras y representa "dd/mm/yy hh:mm:ss"
        super ("##/##/## ##:##:##");
    }

    /** Una clase adecuada para convertir Date a String y viceversa de forma cómoda. Puedes ver cómo se hace el patrón "dd/MM/yy kk:mm:ss" en la API.
        El patrón que pongamos aquí debe cuadrar correctamente con la máscara que hemos puesto en el constructor */

    private SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yy kk:mm:ss");

    /** Convierte el texto del editor en un Date */
    public Object stringToValue(String text) throws ParseException
    {
        return formato.parseObject(text);
    }

    /** Redibe un Date o null y debe convertirlo a texto que cumpla el patrón indicado anteriormente */
    public String valueToString(Object value) throws ParseException
    {
        if (value instanceof Date)
            return formato.format((Date)value);
        return formato.format(new Date());
    }
}

Ya está todo listo. Simplemente instanciamos el JFormattedTextField pasándole nuestro FormatoFecha y le damos un valor inicial válido para evitar problemas. Como nuestro constructor lanza una excepción, hay que meterlo todo en un try-catch.

try
{
    JFormattedTextField textField = new JFormattedTextField(new FormatoFecha());
    textField.setValue(new Date());
}
catch (...)

Puedes ver un Applet funcionando con este editor y descargarte sus fuentes.

El InternationalMaskFormatter

Una AbstractFormatter interesante es el InternationalMaskForamatter. Además de otras muchas cosas, nos permite editar un número sin que se salga de un rango determinado. Por ejemplo, un entero entre 10 y 100. Este AbstractFormatter permite escribir cosas incorrectas, pero al final sólo admite números entre el rango indicado.

Su uso es sencillo, basta algo como esto

InternationalFormatter formato = new InternationalFormatter();
formato.setMaximum(new Integer(100));
formato.setMinimum(new Integer(10));
JFormattedTextField textField = new JFormattedTextField(formato);
textField.setValue(new Integer(90));

Puedes ver un Applet funcionando con este editor y descargarte sus fuentes.

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007: