Usos Interesantes de JFormattedTextField

download Usos Interesantes de JFormattedTextField

of 24

Transcript of Usos Interesantes de JFormattedTextField

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    1/24

    USOS INTERESANTES DE JFormattedTextField

    v. 1.1

    Francesc Ross i Albiol(03/2005)

    Todos los que en alguna ocasin nos hemos tenido que enfrentar al desarrollo de interficies deusuario en Swing nos hemos encontrado con algunas deficiencias en cuanto a los componentesdisponibles. Una de ellas, y creo que importante por su uso masivo en aplicaciones de este tipo, hasido la de los campos de entrada.

    Hasta la aparicin de la versin 1.4 del JDK, slo disponamos de JTextField. Un componentebastante limitado que pona de manifiesto las deficiencias de Swing respecto a otras aproximaciones

    como, por ejemplo, Delphi.Siempre he defendido a Swing respecto a las tpicas aproximaciones de Windows haciendo hincapien la bondad de su arquitectura y las posibilidades que sta ofrece al desarrollador para extender demanera relativamente fcil (o, al menos, ortogonal) los componentes que nos ofrece. Fruto de ellofue la pequea coleccin de widgets que desarroll para JDK 1.2 que inclua, entre otros, un campocon mscara o campos especializados para nmeros.1 Pero la verdad es que, a pesar de dichas

    posibilidades de expansin, si queras algo tan simple como unspinner, te lo tenas que fabricar yeso siempre da pereza y est sujeto a errores difciles de controlar.

    Cuando apareci la versin 1.4 del JDK, tuve la impresin de que Sun haba, de alguna manera,recogido las quejas de los usuarios y se haba decidido a cubrir algunas de las necesidades bsicas

    del desarrollador de interficies de usuario proporcionando, por primera vez en bastante tiempo, doscomponentes bsicos: JSpinner y JFormattedTextField.

    Este artculo, como su ttulo indica, pretende profundizar en las posibilidades que nos ofreceJFormattedTextField.

    JFormattedTextField no es ms que una extensin de JTextField que viene a cubriralgunas de las deficiencias que todos encontrbamos en l.

    Un campo de entrada es un componente que cumple una doble funcin. Por una parte, permite queel usuario entre el texto que se corresponde con un dato solicitado por la aplicacin; y por otra,

    permite a la aplicacin mostrar datos al usuario.

    La principal limitacin que le encuentro a JTextField es que permite entrar cualquier texto yque no hay manera fcil de mostrar un texto con un formato concreto. No hay posibilidad deestablecer un control sobre lo que el usuario entra ni manera sencilla de mostrar convenientementedatos de tipos tan habituales como fechas o nmeros.

    Lo primero que uno piensa cuando se acerca por primera vez a JFormattedTextField esfinalmente tenemos un campo que soporta mscaras. Todos esperbamos este componente. Sinembargo, su nombre no es algo as comoJMaskedTextField. Su nombre nos insina que va ms allde un campo con mscaras. Se trata de un campo de entrada de texto que nos permite especificarformatos. Ciertamente, una manera de especificar un formato de entrada es mediante una mscara,

    pero no es el nico. Adems, como acabo de comentar, un campo de entrada no slo sirve para

    1 Algunos de estos widgets se pueden encontrar en mi Web personal(http://www.froses.com/ES/Descarregues/Widgets.htm).

    1 de 24

    http://www.froses.com/ES/Descarregues/Widgets.htmhttp://www.froses.com/ES/Descarregues/Widgets.htm
  • 8/3/2019 Usos Interesantes de JFormattedTextField

    2/24

    entrar texto. Tambin muestra lo que hemos entrado. Volveremos ms tarde sobre este punto.

    Resumiendo un poco las caractersticas de este componente podemos decir que:

    Distingue entre el valor del campo y el texto que lo representa Permite especificar formatos fijos de entrada de datos, por ejemplo, mediante mscaras Sabe aprovechar el resto de especificaciones de formato disponibles en Java para nmeros,

    fechas, horas, etc. Permite decidir si se admiten caracteres incorrectos en la entrada o no. Permite distinguir entre modalidad de edicin y modalidad de visualizacin. Permite establecer dos modalidades de escritura: insercin y sobrescritura. Permite que decidamos qu hacer con el foco si lo que el usuario ha entrado no es correcto, al

    beneficiarse de las nuevas capacidades del JDK 1.4 para la comprobacin de valores en Swing.

    Bueno, creo que las posibilidades que nos ofrece JFormattedTextField son esperanzadoras eintentar mostrar hasta qu punto.

    Para ello, he pensado dividir el artculo en tres partes diferenciadas con objetivos distintos. Laprimera, muestra los usos ms habituales de JFormattedTextField y comenta cmo usar la

    clase javax.swing.InputVerifierpara controlar el foco en base al valor entrado en elcampo. El objetivo, en esta primera parte, es conseguir que el lector pueda utilizar fcilmenteJFormattedTextField en sus aplicaciones.La segunda discute ms a fondo la arquitectura y el funcionamiento de JFormattedTextField,y tiene como objetivo preparar al lector para poder extender las posibilidades deJFormattedTextField, extendindolo y creando nuevos componentes especializados.En la tercera, presento algunos widgets derivados de JFormattedTextField, y desarrolladosespecficamente para este artculo, que tienen un doble objetivo: mostrar al lector una posible va deexpansin del componente que nos ocupa y proporcionarle unos componentes listos para ser usadosen sus aplicaciones. Tambin proporciono algunas aplicaciones que ejemplifican tanto el uso de

    estos widgets como de algunos aspectos de JFormattedTexField y de las clases derivadas deJFormattedTextField.AbstractFormatter.

    USOS GENERALES DE JFormattedTextFieldComo he comentado ms arriba, el objetivo de este captulo es proporcionar la informacinsuficiente al lector para que pueda hacer uso de las principales funcionalidades deJFormattedTextField.

    Qu esJFormattedTextField?

    JFormattedTextField es un componente derivado de JTextField que, como ste, sirvepara entrar y mostrar datos.

    Una de las caractersticas principales de JFormattedTextField es la de permitir dar formato alos datos, tanto en el momento de entrarlos como en el de visualizarlos.

    Para ello, y a diferencia de JTextField, JFormattedTextField distingue entre el valoralmacenado (una subclase de Object accesible mediante el mtodo getValue()) y el texto quemuestra (una java.lang.String accesible mediante getText()).

    En el siguiente apartado, veremos cmo podemos especificar los distintos formatos.

    2 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    3/24

    Especificacin de formato

    El componente JFormattedTextField nos permite especificar el formato de diversas maneras:

    De manera automtica: Asignando un valor al campoSimplemente asignando un valor al campo, ste nos asigna un formato. As, por ejemplo, si leasignamos una fecha, l nos la permitir editar. El siguiente cdigo crea un campo de entrada parafechas con el formato por defecto:

    JFormattedTextField efFecha = new JFormattedTextField(new Date());

    El campo mostrar la fecha actual con el siguiente formato:19-ago-2002

    Pero no slo nos presenta la fecha. Nos permite editarla de una manera sencilla y sin error posible.Si colocamos, por ejemplo, el cursor sobre el mes y pulsamos la flecha hacia arriba, el mes cambia y

    pasa a sersept. Si pulsamos la flecha hacia abajo, el mes serjul. El mismo comportamiento se dapara el da y el ao. Adems, el comportamiento es inteligente. Supongamos que la fecha sea 28 de

    febrero de 2002 y que aumentemos el da. La nueva fecha sera 1 de marzo de 2002. Lgicamente, siel ao fuera el 2000 (bisiesto) la fecha propuesta sera el 29 de febrero de 2000.

    Mediante una mscaraPodemos utilizar una mscara para determinar el formato. Por ejemplo, si quisiramos crear uncampo para entrar cdigos de cuenta corriente, podramos hacerlo as de fcil:

    MaskFormatter mfCC = new MaskFormatter(####-####-##-##########);mfCC.setPlaceholderCharacter('_');JFormattedTextField efCC = new JformattedTextField(mfCC);

    El campo tendra el siguiente aspecto:

    ____-____-__-__________

    Fijmonos que las partes escribibles se representan con el carcter de subrayado que hemosespecificado con setPlaceholderCharacter().

    La siguiente tabla resume los caracteres utilizables en una mscara:

    Carcter Descripcin

    # Un nmero

    ? Una letra

    A Una letra o un nmero

    * Cualquier cosaU Una letra que ser pasada a mayscula

    L Una letra que ser pasada a minscula

    H Un dgito hexadecimal (A-F, a-f, 0-9)

    ' Carcter de escape para otro carcter de mscara

    Mediante descriptores de formato ya existentesJava nos ofrece una amplia gama de especificaciones de formato para fechas, horas, nmeros y

    monedas. Todos ellos pueden ser utilizados, directa o indirectamente, para especificar el formato

    3 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    4/24

    usado por el campo. Ejemplificaremos algunos de ellos.

    Ms arriba, hemos mostrado cmo especificar un formato de fecha simplemente pasando una alconstructor del campo. El resultado es vistoso, pero cualquier persona que entre datos nos dir quees poco prctico. Sera ms interesante algo del estilo de dd/mm/aa. El siguiente cdigo nosmuestra cmo hacerlo:2

    JFormattedTextField efFecha =new JFormattedTextField(new SimpleDateFormat(dd/MM/yy));

    El resultado obtenido sera: 19/08/02. El comportamiento de las flechas sera el ya descrito.

    Si lo que pretendemos es entrar un nmero con un mximo de dos decimales:JFormattedTextField efNum =new JformattedTextField(new DecimalFormat(#,###.00));

    Si nos interesa que el usuario entre importes en euros en nuestro campo:JFormattedTextField efMon =new JformattedTextField(NumberFormat.getCurrencyInstance());

    efMon.setValue(new Integer(1000));

    Lo que veramos sera:1.000,00

    Admitir o no caracteres incorrectos

    A veces, nos puede interesar permitir que el usuario pueda entrar caracteres incorrectos. Parahacerlo, usaremos formateadores propios de JFormattedTextField. Veamos el siguienteejemplo:3

    JFormattedTextField efNum =new JformattedTextField(new DecimalFormat(#,###.00));

    NumberFormatter nf = (NumberFormatter)efNum.getFormatter();nf.setAllowsInvalid(true)

    ;Disponemos de tres formateadores especiales derivados todos ellos de la clasejavax.swing.JFormattedTextField.AbstractFormatter:

    MaskFormatter Utilizado para mscaras y derivado directamente deAbstractFormatter.

    NumberFormatter Utilizado para nmeros y derivado de una subclase deAbstractFormatter: InternationalFormatter.

    DateFormatter Utilizado para fechas y horas y derivado, como el anterior, deInternationalFormatter.

    Insertar o sobrescribirAlgo de sumo inters es poder especificar si insertamos o sobrescribimos caracteres. Lo ideal seraque se pudiera decidir pulsando la tecla , pero esto no es inmediato.

    El siguiente ejemplo nos indica cmo permitir la sobrescritura:4

    2 Los componentes DateField, DecimalField, DecimalFieldScrollable , IntegerField,MoneyField y PercentField, comentadas ms abajo, ilustran la asignacin de diversos formatos y se incluyenen el cdigo fuente de este artculo.

    3 La aplicacin de ejemplo IntegerFieldTest , comentada ms abajo, nos permite comprobar el funcionamientode setAllowsInvalid(boolean) .

    4 El componente DefaultJFormattedTextField , comentado ms abajo, implementa los mtodos de inserciny sobrescritura y se incluye en el cdigo fuente de este artculo.

    4 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    5/24

    JFormattedTextField efNum =new JformattedTextField(new DecimalFormat(#,###.00));

    NumberFormatter nf = (NumberFormatter)efNum.getFormatter();nf.setOverrideMode(true);

    Modalidad de edicin y de visualizacin

    Imaginemos que tenemos un campo para entrar importes en euros como el que hemos descrito msarriba. El resultado obtenido es interesante; se ve bien, con el smbolo de euro al final y losseparadores de millares y la coma decimal siguiendo las directrices de nuestro pas. Pero una vezms, un usuario que se dedique a entrar datos nos dira que es incmodo. Normalmente, se usa elteclado numrico y uno no tiene que ir a buscar la coma al teclado alfanumrico. Usa un punto paraindicar la coma. Claro que si bien es prctico entrar1234.35, queda mal cuando se visualiza.Tenemos, pues, un conflicto: lo que es prctico para la entrada de datos no es claro en lavisualizacin.

    JFormattedTextField nos permite resolver este conflicto especificando un formato para laedicin y otro para la visualizacin. Cuando el foco est en el campo, usar el de edicin y cuandoste pierda el foco, usar el de visualizacin.5

    Veamos cmo hacerlo para nuestro campo de importes en euros:

    // Creamos el campoJFormattedTextField efDecimal =

    new JformattedTextField();

    // Formato de visualizacinNumberFormat dispFormat = NumberFormat.getCurrencyInstance();

    // Formato de edicin: ingls (separador decimal: el punto)NumberFormat editFormat =

    NumberFormat.getNumberInstance(Locale.ENGLISH);

    // Para la edicin, no queremos separadores de millareseditFormat.setGroupingUsed(false);

    // Creamos los formateadores de nmerosNumberFormatter dnFormat = new NumberFormatter(dispFormat);NumberFormatter enFormat = new NumberFormatter(editFormat);

    // Creamos la factora de formateadores especificando los// formateadores por defecto, de visualizacin y de edicinDefaultFormatterFactory currFactory =new DefaultFormatterFactory(dnFormat, dnFormat, enFormat);

    // El formateador de edicin admite caracteres incorrectosenFormat.setAllowsInvalid(true);

    // Asignamos la factora al campoefDecimal.setFormatterFactory(currFactory);

    Editamos en formato ingls (usamos el punto como separador decimal) y sin separadores demillares.

    Visualizamos lo que hemos entrado en el formato de moneda y numrico de nuestro pas. En estecaso, el euro como smbolo de moneda, el punto como separador de millares y la coma comoseparador decimal, pero si el programa se ejecutara en Inglaterra, veran el smbolo de la Libra, lacoma sera el separador de millares y el punto, el separador decimal.

    5 Los componentes DecimalField, DecimalFieldScrollable , IntegerField, PercentField y

    MoneyField, comentadas ms abajo e incluidas en el cdigo fuente de este artculo, ilustran el uso de formatosdistintos para la edicin y la visualizacin.

    5 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    6/24

    La siguiente imagen muestra nuestro campo en modalidad de edicin:

    La siguiente imagen muestra el mismo campo en modalidad de visualizacin:

    Si observamos el cdigo, veremos que opto por admitir caracteres incorrectos en edicin. El motivoes que NumberFormatter define el comportamiento de las teclas ms (+) y menos (-) haciendoque sean las responsables del cambio de signo. No escriben el signo, sino que lo cambian. Por ello,y para hacer que la escritura se parezca ms a la que solemos utilizar, he decidido permitir el uso decaracteres incorrectos en el ejemplo.

    Control del foco:InputVerifier

    Uno de los problemas tpicos en el desarrollo de interficies grficas para la entrada de datos esdecidir qu se hace cuando el usuario que ha rellenado incorrectamente un campo quiere pasar alsiguiente. En algunos casos nos puede interesar que lo pueda hacer, pero en otros no.

    Imaginemos que necesitamos un campo para entrar nmeros de DNI, con su letra. Este campo, ennuestra aplicacin, es clave ya que a partir de l, se obtiene el resto de la informacin. As, pues, siel nmero entrado fuera incorrecto, no debiramos permitir que el usuario saltara al camposiguiente.

    Anteriormente, haba que utilizar algn truco (que no viene al caso) para evitar que el foco se fueraal siguiente componente. En la versin 1.3 del JDK, se nos facilita bastante el trabajo. Podemosasignar al campo una clase que extienda InputVerifiermediante el mtodosetInputVerifier() de manera que sea esta clase la que controle si el usuario podr salir delcampo (pasar el foco a otro componente) o no.

    Para seguir con el ejemplo del DNI, proponemos un pequeo ejemplo que ilustre el procedimiento.6

    Vamos a definir una mscara que facilite la entrada de DNIs en nuestro campo:// Definicin de la mscara de DNIMaskFormatter maskDNI = null;try {maskDNI = new MaskFormatter("##.###.###-U");

    } catch (ParseException e) {// De momento, no hacemos nada

    }// El carcter a mostrar en las posiciones escribibles es el

    // subrayado.maskDNI.setPlaceholderCharacter('_');

    La mscara obligar al usuario a entrar ocho dgitos y una letra que ser pasada a maysculas.Adems, mediante el mtodo setPlaceholderCharacter(), asignamos un carcter desubrayado para que sirva de pauta al usuario, indicndole las posiciones editables del campo.

    El carcterUque vemos en la mscara obligar al usuario a escribir la letra del DNI y pasar dichaletra a maysculas.

    La mscara se encargar, pues, de que el usuario escriba dgitos y letras donde corresponda, pero elvalor entrado no ser entregado al campo directamente hasta que pulsemos la tecla Intro. Al

    6 El componente DNIField, cuyo cdigo fuente se incluye, es un ejemplo completo de campo destinado a la entradade DNIs.

    6 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    7/24

    cambiar de foco, el MaskFormatter no entrega el valor. Hay que decirle explcitamente que si loeditado es vlido, pase el valor al campo. Para ello, utilizaremos el mtodosetCommitsOnValidEdit(boolean).

    maskDNI.setCommitsOnValidEdit(true);

    Si comentamos esta lnea, veremos que al entrar un DNI incorrecto nos deja cambiar el foco debidoa que el valor no se ha entregado al campo para que determine si debe permitir el cambio de foco ono.

    Finalmente, creamos el campo:JFormattedTextField efDNI = new JformattedTextField(maskDNI);

    En este momento, ya hemos dotado a nuestro campo de un cierto control para entrar DNIs:

    Nos fuerza a escribir los nmeros y la letra en los lugares que corresponde

    Pasa automticamente la letra final de control a maysculas

    Sin embargo, la mscara no nos proporciona todo el control que necesitamos. Si la persona queentra los datos se equivoca en la letra de control, el error queda registrado. Necesitamos, pues,

    impedir que la persona que entra los datos entre un DNI errneo (aunque, y de eso se encarga lamscara, bien formado).

    La versin 1.3 del JDK incorpora un nuevo mtodo a la clase javax.swing.JComponent:setInputVerifier(InputVerifier v). Este mtodo nos permite asignar a unJFormattedTextField un algoritmo de control del contenido entrado. Este algoritmo decontrol se hallar embebido en una subclase de InputVerifier. La clase InputVerifier esabstracta y obliga a sus subclases a implementar el mtodo public booleanverify(JComponent input). Este mtodo devuelve true, si la comprobacin es correcta, ofalse, si no lo es.

    Veamos ahora la clase derivada deInputVerifierque se encarga de verificar si el DNI entrado

    es correcto y permite al campo decidir si autoriza, o no, el cambio de foco.Disponemos de la clase CIF_NIF, con el mtodo esttico boolean isNIFOK(String DNI)que nos devuelve true o false en funcin del DNI pasado como parmetro.7

    Creamos, por ejemplo, la clase ValidateDNI que extiende InputVerifier:

    class ValidateDNI extends InputVerifier {

    /*** Sobrescribimos el mtodo del padre para realizar la* comprobacin del DNI entrado.*/public boolean verify(JComponent input) {

    if (input instanceof JFormattedTextField) {Object o = ((JFormattedTextField)input).getValue();if (o == null) return true;

    String value = o.toString();return CIF_NIF.isNIFOK(value);

    }return false;

    }

    El mtodo verify() se encarga de llamar al mtodo CIG_NIF.isNIFOK() que contiene elalgoritmo de verificacin de DNIs. Si este mtodo da el DNI por bueno, el usuario podr cambiar el

    7 La clase CIF_NIF, comentada ms abajo, se incluye en el cdigo fuente de este artculo.

    7 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    8/24

    foco. Si no es as, el foco permanecer en el campo de DNI.8

    CMO FUNCIONA EN REALIDAD?En la primera parte de este artculo he intentado que el lector disponga de la informacin suficiente

    sobre JFormattedTextField para que se anime a usarlo en sus aplicaciones. Buena parte de lainformacin que el lector ha encontrado en la primera parte puede, tambin, encontrarla en diversostutoriales. El de Sun, por ejemplo, nos muestra algunos ejemplos parecidos a los que he descrito.Sin embargo, ni sus ejemplos, ni los que yo he presentado son realmente serios. Simplemente

    pretenden ilustrar algunas de las funcionalidades bsicas de los distintos elementos implicados enJFormattedTextField.

    Para esta segunda parte, me he propuesto intentar proporcionar a lector la informacin necesariapara poder usar aquellos aspectos poco evidentes de JFormattedTextField.

    La informacin que aqu presento es fruto del estudio directo de las distintas APIs implicadas enJFormattedTextField y del cdigo fuente de las distintas clases. Espero que le ahorre trabajo

    al lector.

    Observaciones generales

    JFormattedTextField siempre almacena como valor un objeto (una subclase de Object).Este valor, sin embargo, debe ser representado como una tira de caracteres (una String) ya queJFormattedTextField no es sino una subclase de JTextField, quien, como su propionombre indica, es un campo de texto.

    Esto no es problema para JTextField, ya que siempre almacena objetos de tipo String, peropara JFormattedTextField no es tan evidente. Alguien tiene que transformar este objeto en

    una String para que pueda ser representado.Volviendo al nombre de nuestro componente, JFormattedTextField, observamos quecontiene el adjetivoformatted(formateado, con formato). Este es un detalle importante. Latransformacin del objeto almacenado a String comporta un proceso de aplicacin de formato.Resumiendo, JFormattedTextField :

    1. Toma el valor que le asignamos,

    2. crea una tira de caracteres convenientemente formateada segn algn criterio y

    3. la muestra en el campo

    Pero hemos comentado ms arriba que el valor no slo se asigna y se ve, sino que se edita. Es decir,

    que hay un formato de edicin y que quien controla este formato se encarga de decidir, por ejemplo,si en tal posicin podemos escribir un nmero o una letra o si podemos escribir o no en una posicinconcreta.

    El formato

    Los responsables del formato, tanto del de edicin como del de visualizacin, son losformateadores. Un formateador es, en realidad, una clase derivada deJFormattedTextField.AbstractFormattery cumple diversas funciones.

    En modo de edicin, decide qu se puede escribir y dnde y cmo y cundo pasa el valor editado al

    8 El componente de ejemplo DNIField, descrito ms abajo, se incluye en el cdigo fuente de este artculo.

    8 de 24

    http://java.sun.com/docs/books/tutorial/uiswing/components/formattedtextfield.htmlhttp://java.sun.com/docs/books/tutorial/uiswing/components/formattedtextfield.html
  • 8/3/2019 Usos Interesantes de JFormattedTextField

    9/24

    campo.

    Por ejemplo, si usamos un formato numrico, y no permitimos la insercin de caracteresincorrectos, no podremos teclear ninguna letra. En el campo de DNI que he puesto de ejemplo,nunca podremos escribir sobre el guin de separacin de la letra de control, a pesar de queMaskFormatter use el modo de sobrescritura por defecto.

    En algunos casos, el formateador tambin define el comportamiento del teclado. Por ejemplo,DateFormatter permite el incremento o decremento de los distintos campos de una fecha (da,mes, etc.) mediante las flechas del teclado.

    En modo de visualizacin, decide cmo se muestra el valor almacenado en el campo. As, en laaplicacin de ejemplo MoneyFieldTest, podremos comprobar que el valor almacenado comoBigDecimal en un campo MoneyField, en modo de visualizacin, se muestra como un nmeroy un carcter de moneda.

    Un formateador transforma un valor (esto es, un Object) a una tira de caracteres usando el mtodovalueToString(Object) y una tira de caracteres a un valor (esto es, un Object) usando elmtodo stringToValue(String). Estos son los mtodos que le permiten almacenar lo

    editado como una subclase de Object y mostrar este valor como una tira de caracteres en elcampo.

    La siguiente figura muestra la jerarqua de clases de los distintos formateadores:

    El ms sencillo es DefaultFormatter que se utiliza para formatear objetos arbitrarios. Elmtodo valueToString(), simplemente, devuelve el resultado del mtodo toString() delvalor almacenado. Y para almacenar una tira como valor, usa un constructor de la clase del objetoque tenga como parmetro una tira de caracteres.

    InternationalFormatter es una subclase de DefaultFormatter que usajava.text.Format para pasar de String a Object y viceversa.Por defecto, slo admite caracteres correctos (setAllowsInvalid(false)), por lo que no es

    conveniente modificar esta propiedad si no queremos tener problemas.

    9 de 24

    Figura 1: Jerarqua de formateadores

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    10/24

    Tambin se encarga de ajustar la posicin del cursor, situndolo sobre aquellas posiciones en lasque se puede escribir.

    NumberFormatter es una subclase de InternationalFormatter diseada especialmentepara la entrada de nmeros.Entre otras cosas, establece el comportamiento de la tecla de manera que, estemos dondeestemos del campo, convierte el nmero entrado en negativo.9 La tecla pasa el nmero a

    positivo. Esto es, desaparece el signo menos.

    DateFormatter es una subclase de InternationalFormatterdiseada especialmentepara la entrada de fechas.Como hemos comentado ms arriba, define el comportamiento de las flechas del teclado paraaumentar o disminuir das, meses, aos, etc.

    La clase MaskFormatter extiende DefaultFormatter y est pensada especialmente para laedicin de tiras de caracteres con formatos especficos. Como hemos visto ms arriba, se basa enuna mscara que indica qu caracteres se pueden escribir en una posicin determinada.

    Personalizacin de los formateadoresTodos los formateadores tienen comportamientos por defecto. Por ejemplo, DateFormatter noadmite caracteres incorrectos en la edicin y MaskFormatter est siempre en modo desobrescritura.

    Pero podemos cambiar alguno de estos comportamientos o acceder a alguna de sus caractersticas yaque nos proporcionan mtodos de acceso. As, DefaultFormatter nos proporciona lossiguientes mtodos:10

    setAllowsInvalid(boolean): Nos permite decidir si aceptamos caracteresincorrectos o no.

    setCommitsOnValidEdit(boolean): Nos permite, en modo de edicin, decidircundo se libra el valor de lo que estamos escribiendo al campo. Si usamos true comoparmetro, cada vez que escribamos algo se validar y, si es correcto, se asignar como valordel campo.

    setOverwriteMode(boolean): Nos permite decidir si la modalidad de edicin essobrescritura (true) o insercin (false).

    InternationalFormatter nos ofrece tres posibilidades interesantes como:

    setMaximum(Comparable): Para establecer el valor mximo admisible por el campo.

    setMinimum(Comparable): Para establecer el valor mnimo admisible por el campo.11

    getFields(int offset): Para determinar qu campo (entero, decimal, signo, etc.) secorresponde con una posicin determinada.12

    9 Curiosamente, si no hemos entrado ningn texto o valor y no permitimos la entrada de caracteres incorrectos, pulsarla tecla no sirve de nada.

    10 En los componentes que he desarrollado de ejemplo, he considerado necesario facilitar el acceso a alguno de losmtodos de personalizacin de formateadores desde el propio componente. As, por ejemplo, los componentesponen a disposicin del programador mtodos como setOverwriteMode(boolean)osetAllowInvalidCharacters(boolean) .

    11 Los mtodos setMaximum(Comparable) y setMinimum(Comparable) se han implementado en loscomponentes de ejemplo DefaultNumberField , IntegerField, DecimalField. Esto permite establecerrangos de valores aceptables para instancias de dichos componentes y de sus subclases PercentField y

    MoneyField.12 Vase el mtodo sum(int sign) del componente de ejemplo DefaultNumberField .

    10 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    11/24

    A falta de pruebas intensivas, observo que si, habiendo definido un rango de valores aceptable paraun InternationalFormater, asignamos un valor fuera del rango definido mediante el mtodosetValue(object), no se tiene en cuenta el rango y el valor se asigna sin problemas alcampo.13

    MaskFormatter nos obsequia con algunos mtodos realmente tiles:

    setInvalidCharacters(String): Nos permite especificar una lista de caracteresque no sern aceptados por el campo.Supongamos, por ejemplo, que tenemos un campo con una mscara para entrar cdigos de

    producto. La mscara podra ser parecida a sta: U###. Es decir, un carcter alfabtico queser pasado a maysculas, seguido de tres dgitos. Es de esperar que el usuario no entre unaletra acentuada en la primera posicin de la mscara, pero los usuarios son muy listos yseguro que ms de uno lo intentar. Si recordamos la sintaxis para la especificacin demscaras, observaremos que no hay ninguna manera de especificar que no admitiremoscaracteres acentuados. Por lo tanto, el usuario astuto puede entrar una y fastidiarnos laaplicacin. La manera de impedirlo es, pues, usando el mtodosetInvalidCharacters() al que se le pasar como parmetro una String con todos

    los caracteres acentuados (en maysculas). setValidCharacters(String): Nos permite especificar la lista de caracteres que

    sern aceptados.Se trata del mtodo complementario del anterior. Siguiendo con el mismo ejemplo,

    podramos especificar que los caracteres aceptables sonABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.

    setPlaceHolder(String) y setPlaceHolderChracter(char): permiten,como hemos visto ms arriba, especificar los caracteres que no se mostrarn en las

    posiciones escribibles. En el ejemplo del campo de DNI, el carcter utilizado era el desubrayado.

    setValueContainsLitteralCharacters(boolean): Nos permite decidir si losvalores entrados, con setValue(), o recuperados, con getValue(), contienen tambinlos literales incluidos en la mscara (true) o no (false).As, si nuestra mscara para DNI es ##.###.###-U y hemos especificado true,getValue(), nos devolver 12.345.678-A. Si, por el contrario, especificamosfalse, nos devolver 12345678A. De igual manera, si hemos especificado true, el

    parmetro para setValue() tendr que ser12.345.678-A y si hemos especificadofalse, 12345678A.

    Asignacin de formatosLa nica manera que tenemos de asignar formatos a un JFormattedTextField es medianteuna subclase de JformattedTextField.AbstractFormatterFactory. Normalmente,

    pues, usaremos la nica existente: DefaultFormatterFactory.

    DefaultFormatterFactorypermite especificar cuatro AbstractFormatters para tressituaciones distintas:

    1. Formato por defecto: Se usa si no hay otro definido para una situacin concreta, lo cualimplica que se usar tanto como formato de edicin como de visualizacin y como nulo, si

    13 Esto es debido a las diferencias de comportamiento entre setValue() y commitEdit() que se comentan ms

    abajo. Este comportamiento ha sido corregido en los componentes numricos de ejemplo. Si se intenta asignar unvalor fuera de rango, se lanza una IllegalArgumentException .

    11 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    12/24

    slo especificamos ste.

    2. Formato de edicin: Se usa cuando el campo tiene el foco y sirve para facilitar la edicin

    3. Formato de visualizacin: Se usa cuando el campo no tiene el foco y se utiliza para mostrarel valor

    4. Formato nulo: Se usa cuando el campo tiene un valor nulo (null)

    Los procesos

    En el apartado Observaciones generales, he presentado un breve esquema de los principalesprocesos que realiza JFormattedTextField para almacenar un valor y mostrarlo. Vamosahora a entrar con un poco ms de detalle en estos procesos.

    Asignacin del valorMientras estamos escribiendo, JFormattedTextField no asume, en principio, ningn valor.

    Lo que escribimos est, por as decirlo, en el aire y slo se puede obtener con el mtodogetText() comn a todos los JtextComponents. La excepcin a dicho comportamiento esten el hecho de especificarsetCommitsOnValidEdit(true)para el formateadorcorrespondiente, como hemos comentado ms arriba.

    Hay dos maneras de asignar un valor al campo: de manera automtica y por programa.

    Asignacin de valor automtica

    Cuando pulsamos o cuando cambiamos el foco, empieza el proceso de asignacinautomtica de valor.

    A grandes rasgos, lo que sucede al pulsar o cambiar el foco es lo siguiente:1. Ejecuta el mtodo commitEdit(). Este mira si hay un AbstractFormatter definido

    que se encargue de transformar el texto en un objeto. Si no lo encuentra, no asigna valor. Esdecir, si usamos el mtodo getValue() de JFormattedTextField, nos devolvernull.

    2. Si encuentra el AbstractFormatter, obtendr el texto entrado mediante getText()y usar el mtodo stringToValue() para obtener el objeto correspondiente y asignarlo.El proceso de transformacin de una tira a un objeto, comporta un anlisis de la tira y es

    posible que no funcione. En este caso, el AbstractFormatter generar unaParseException y no se asignar ningn valor.

    Un ejemplo tpico sera el intento de asignacin de la tira 1OOO (obsrvese que en vez deceros hay os maysculas) mediante un NumberFormatter. ste intentar convertir estatira en un Long y se producir una excepcin. El resultado es que getValue() nosdevolver null o el ltimo valor correcto entrado.

    Pero JFormattedTextField nos permite afinar un poco ms en el caso de la asignacin devalor por cambio de foco y nos permite establecer polticas a seguir. Para ello usaremos el mtodoJFormattedTextField.setFocusLostBehavior(int behavior). La siguiente tablalas resume:

    12 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    13/24

    Valor Descripcin

    JFormattedTextField.REVERT Revierte lo editado al ltimo valoralmacenado en el campo. Es decir, al valordevuelto por el mtodo getValue(). Sino hay ningn valor almacenado

    previamente o no forzamos unsetValue(), por ejemplo, pulsando, el contenido de la edicinactual se perder.

    JFormattedTextField.COMMIT Entrega el valor actual al perder el foco. Siel valor editado no es considerado un valorlegal por el AbstractFormatter (estoes, se lanza una ParseException),entonces el valor editado no cambiar perono se asignar como valor.

    Resumiendo, se comporta como COMMIT,pero si el valor editado no es correcto, nolimpia el campo.

    JFormattedTextField.COMMIT_OR_REVERT Es similar a COMMIT, pero si el valor queescribimos no es legal (esto es, elAbstractFormatter lanza unaParseException), se comporta comoREVERT y limpia el contenido del campo.

    JFormattedTextField.PERSIST No hace nada, no obtiene un nuevoAbstractFormatter y no actualiza el

    valor. Sea correcto o incorrecto lo queentremos, mantiene el valor correctoanterior pero no limpia el campo.

    Tabla 1: Polticas de asignacin de valor en la prdida de foco

    La poltica por defecto es COMMIT_OR_REVERT.14

    Asignacin de valor por programa

    A grandes rasgos, el proceso de asignacin funciona de manera similar a la asignacin automtica.

    Disponemos de dos mtodos para asignar un valor: setValue(Object valor) ycommitEdit(), descrito ms arriba. El ms ms usado es setValue(Object). El proceso,resumido, es el siguiente:

    1. Mira si dispone de un formateador (en este caso, mira si hay definida unaFormatterFactory).

    2. Si no hay ninguna definida, la crea basndose en la clase del objeto pasado como parmetro.Este objeto debe ser una instancia de DateFormat, NumberFormat, Format, Date oNumber. JFormattedTextField crear una DefaultFormatterFactorybasadaen el tipo del valor que intentamos asignar. Si se trata de una instancia de DateFormat,

    14 La aplicacin de ejemplo IntegerFieldTest permite hacer pruebas con las distintas polticas de prdida defoco y con el mtodo setCommitsOnValidEdit(boolean) .

    13 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    14/24

    crear una DefaultFormatterFactorybasada en un DateFormatter, si es unainstancia de NumberFormat, usar un NumberFormatter, si es una Date, usarDateFormatter, si es un Format, usar InternationalFormatter, si se trata deun Number, usar un NumberFormatter como formateador por defecto y paravisualizacin y un NumberFormatter especial que usa un DecimalFormat con el

    patrn #.# para la edicin.

    3. Asigna el valor.

    Observamos una diferencia notable entre commitEdit() y setValue(). El primero usa elmtodo stringToValue() para obtener el valor a pasar como parmetro de setValue(),mientras que ste asigna el valor directamente. Esto es, commitEdit() puede recibir unaParseException como resultado de invocarstringToValue() si el formateador detecta unerror de formato.

    Hemos de hablar, pues, de un comportamiento asimtrico entre commitEdit() y setValue()que no suele tener consecuencias. Sin embargo, hay algn caso en que esta asimetra comportaalgn que otro problema. Veamos un ejemplo:

    Nosotros construimos un campo para entrada de DNIs con un MaskFormatter, tal y comohemos visto ms arriba. Pero ahora decidimos que el valor del campo no debe contener literales y loespecificamos usando el mtodo valueContainsLitteralCharacters(false). Siasignamos como valor, por ejemplo, 12.345.678-Z, usando setValue(), no se produceningn error ya que no interviene para nada el formateador. Es ms, getValue() devuelve12.345.678-Z en vez de 12345678Z.15

    15 Esta asimetra ha sido corregida para el componente de ejemplo DNIField. El mtodo setValue() llamasiempre al formateador para comprobar errores de formato.

    14 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    15/24

    APLICACIONES DE EJEMPLOPara ilustrar los conceptos tratados en este artculo, he desarrollado una serie de aplicaciones.Dichas aplicaciones se incluyen con el cdigo fuente correspondiente para que el lector puedaestudiarlas y modificarlas a su conveniencia.

    He procurado que los ejemplos no sean abstractos sino que sean prcticos y usables para cualquierdesarrollador.

    He clasificado los ejemplos en tres categoras:

    1. Componentes auxiliares: se usan en las aplicaciones de demostracin y tienen poco que vercon JFormattedTextField. A pesar de ello, creo que algunas de ellas pueden ser

    bastante interesantes para los desarrolladores.

    2. Componentes derivados de JFormattedTextField: son un conjunto de subclases deJFormattedTextField que, a mi entender, cumplen un doble objetivo. Por una parteilustran la mayor parte de conceptos relacionados con JFormattedTextField y con losdistintos formateadores y por otra, constituyen un conjunto de componentes (en ingls, losllamaran widgets) especializados en distintas tareas (entrada de nmeros, porcentajes,fechas y DNIs) listos para ser utilizados por cualquier desarrollador.

    La estrategia seguida para el desarrollo de los componentes ha sido doble. Por una parte, heaadido funcionalidades que no estn directamente relacionadas con JFormattedTextField,como la aritmtica de fechas, la asignacin de escala a un valor decimal o laautocomplecin de un DNI y, por otro, he hecho emerger, a nivel de componente,

    propiedades del formateador, como la asignacin dinmica del formato de representacin defechas o la especificacin de rango para los campos numricos.

    3. Aplicaciones de demostracin: se trata de pequeas aplicaciones que ilustran tanto elfuncionamiento de los distintos componentes descritos en el punto anterior, como el dealgunos aspectos de JFormattedTextField y de los formateadores.

    A continuacin, paso a describir brevemente cada una de ellas.

    Componentes auxiliares

    CIF_NIFEs una clase que proporciona una serie de mtodos estticos para la verificacin de CIFs y NIFsespaoles. Contiene una amplia documentacin sobre las fuentes en las que me he basado paraescribirla y la casustica que se trata.

    Destacara las siguientes funcionalidades:

    Determina si una tira se corresponde con un NIF o con un CIF

    Determina si un NIF o un CIF son correctos

    Dado un NIF sin letra de control, calcula y devuelve dicha letra

    Trata NIEs (NIFs para extranjeros)

    Esta clase se utiliza en el componente DNIField.

    BoundJSpinnerEs una subclase de JSpinner que tiene la propiedad valuebound. Esto es, cada vez que el valor

    15 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    16/24

    de BoundJSpinner cambia, se genera un PropertyChangeEvent. Se usa en lasdemostraciones de algunos de los componentes.

    ButtonGroupJPanelEs una subclase de JPanel que facilita el uso de JRadioButons desde un editor visual.

    Si queremos un comportamiento normal de mutua exclusin de JRadioButons (esto es, quecuando se pulse en uno el que estaba seleccionado deje de estarlo), es necesario aadir todos losJRadioButons a un ButtonGroup. ButtonGroupPanel, se encarga de ello por nosotros.

    ButtonGroupPanel est basado en un ejemplo de Scott Stanchfield (http://www.javadude.com)y se usa en las demostraciones de algunos componentes.

    OverwriteCaretEs una subclase de DefaultCaret que dibuja un cursor horizontal. Se utiliza para indicar queestamos en modalidad de sobrescritura.

    PairUn simple bean no visual que mantiene una pareja de tipo clave/descripcin. Se usa en losJCombobox de algunas de las demostraciones de los componentes.

    Componentes derivados deJFormattedTextField

    Son componentes de ejemplo, usables,16 que llevan a la prctica todo lo que he intentado explicarsobre JFormattedTextField y su entorno.

    Recomiendo vivamente al lector que estudie con cario el cdigo fuente y lea losjavadocs de lasdistintas clases. Creo que esto va a ser ms prctico (y ms corto) que entrar en los detalles dediseo de cada una de los componentes.

    EnhancedJFormattedTextFieldEs una interface que establece los mtodos, y por ende las funcionalidades, generales del conjuntode componentes.

    DefaultJFormattedTextFieldEs una subclase abstracta de JFormattedTextField que implementa la interfaceEnhancedJFormattedTextFieldy que contiene cdigo para funcionalidades comunes al

    resto de los componentes. Destaco las siguientes: Gestin y creacin de la AbstractFormatterFactoryusada por los distintos

    subcomponentes.

    Posibilidad de establecer la modalidad de escritura y mostrar un cursor diferente para cadamodalidad.

    La asignacin de dicha funcionalidad a la tecla , que intercambia las dos modalidadesde escritura.

    16 A pesar de haber realizado una infinitud de pruebas y de disear y ejecutar pruebas unitarias, puede que los

    componentes no se comporten como debieran. Los proporciono a guisa de ejemplos y no me responsabilizo de losefectos colaterales que se deriven de su uso en produccin.

    16 de 24

    http://www.javadude.com/http://www.javadude.com/
  • 8/3/2019 Usos Interesantes de JFormattedTextField

    17/24

    Implementa el mtodo clear() que permite borrar el contenido de un campo.

    Hace accesibles, a nivel de componente, el uso de los mtodossetCommitsOnValidEdit(boolean)y getCommitsOnValidEdit()deDefaultFormatter.

    Implementa, a nivel de componente, la poltica de aceptacin de caracteres incorrectos del

    formateador. Implementa, a nivel de componente, la poltica de establecimiento y gestin de rangos de

    valores aceptables.

    Implementa el mtodo isEmpty() que nos indica si el campo est vaco..

    DefaultNumberFieldEs una subclase abstracta de DefaultJFormattedTextFieldque contiene cdigo para lasfuncionalidades comunes de los campos numricos (DecimalField, IntegerField,MoneyField y PercentField). Por ejemplo, define el comportamiento del teclado para quelas flechas sirvan para incrementar o decrementar el valor almacenado en el campo o permiteestablecer un rango de valores para los componentes numricos.

    DecimalFieldExtiende DefaultNumberField adaptndolo a la presentacin y edicin de nmeros decimales.

    Destacar las siguientes funcionalidades:

    Distingue el modo de presentacin, en el que muestra separadores de millares y un carcterde separacin decimal acorde con el Locale, del de edicin, en el que se facilita el uso delteclado numrico

    Permite establecer diversas polticas de redondeo Permite determinar la escala

    Los valores entrados se almacenan siempre como BigDecimals

    Se le puede asignar cualquier valor derivado de Number, pero tambin valores de tiposnativos (int, long, byte, short, float, double, etc.). Internamente, se almacenancomo BigDecimals

    IntegerFieldEs una subclase de DefaultNumberField que facilita la edicin y presentacin de nmeros

    enteros.Se le puede asignar cualquier valor derivado de Number (si el valor tiene decimales, slo se tomala parte entera) pero tambin valores de tipos nativos (int, long, byte, short, float,double, etc.). Internamente, se almacenan como BigInteger.

    MoneyFieldExtiende DecimalField asignando como formato de visualizacin el de moneda.

    PercentField

    Extiende DecimalField asignando como formato de visualizacin el de porcentaje.

    17 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    18/24

    DNIFieldEs una subclase de DefaultJFormattedTextFieldque facilita la entrada y validacin deDNIs espaoles mediante una mscara de entrada.

    Funcionalidades destacables:

    Permite determinar si el DNI entrado es correcto (boolean DNIField.isOK())

    Permite la activacin y desactivacin del proceso de verificacin.Si est activada la verificacin y el valor entrado no es correcto, se deshabilita el cambio defoco.

    Permite completar el DNI con la letra de control correcta pulsando o,tambin, cuando el campo pierde el foco.

    Evita la entrada de letras de control no admisibles para DNIs.

    DateField

    Es una subclase de DefaultFormattedTextFieldque facilita la entrada, visualizacin ymanejo de fechas y horas.

    Destaco las siguientes funcionalidades:

    Admite valores asignables de tipo Date y Calendar

    Permite cambiar dinmicamente el formato de visualizacin (el de edicin es el mismo queel de visualizacin) especificando patrones con sintaxis de SimpleDateFormat

    Implementa una aritmtica simple de fechas. Permite aadir o quitar das, semanas, meses,aos, horas, minutos o segundos a la fecha almacenada como valor en el campo de manerasencilla (p.e. addMonths(3), aadira tres meses, addWeeks(-3) restara tres semanas

    a la fecha).

    StringFieldExtiende DefaultFormattedTextFieldpara facilitar la escritura de texto.

    Si bien Swingnos proporciona ya un campo de texto, JTextField, considero que no es suficientepara cubir algunas de las necesidades ms importantes de un campo de este estilo. As, por ejemplo,JTextField slo nos proporciona un mtodo de escritura, la insercin, y no nos permitedeterminar la longitud mxima del texto a escribir.

    Este segundo aspecto es importante si tenemos ligado el texto a alguna columna de una tabla en unabase de datos. Si usamos JTextField, no podemos asegurar que el texto entrado por el usuariotenga una longitud inferior o igual a la definida para la columna de la tabla, por lo que nos veremosobligados ha controlar este hecho por programa. StringField nos permite delegar en lainterficie dicho control al permitirnos determinar la longitud mxima admisible para el texto.

    StringField nos permite, tambin, establecer una poltica de recorte para la asignacin devalor. Si la activamos, usando el mtodo setStripOn(boolean), al intentar asignar un valorcon una longitud superior a la permitida, ste ser recortado convenientemente antes de serasignado. Si no la tenemos activada, consecuentemente, lanzar unaIllegalArgumentException al intentar asignar un valor con una longitud superior a la

    permitida.

    18 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    19/24

    Aplicaciones de demostracin

    Siempre se ha dicho que una imagen (en nuestro caso, una aplicacin visual) vale ms que milpalabras. Es por este motivo que he creado una serie de aplicaciones de escritorio que pretendenejemplificar las funcionalidades de cada uno de los componentes comentados en el apartadoanterior.

    As, pues, el lector dispone de un ejemplo de uso para cada uno de los componentes derivados deJFormattedTextField:

    DecimalFieldTest Ilustra las posibilidades de DecimalField

    IntegerFieldTest Ilustra las posibilidades de IntegerField y las distintaspolticas de comportamiento de JFormattedTextField con la prdida de foco.Tambin muestra las posibilidades de uso de setAllowsInvalid(). Permite, a su vez,verificar las asignaciones de valor cuando hay prdida de foco en funcin de la polticadefinida.

    MoneyFieldTest Ilustra las posibilidades de MoneyField

    PercentFieldTest Ilustra las posibilidades de PercentField DNIFieldTest Ilustra las posibilidades de DNIField

    DateFieldTest Ilustra las posibilidades de DateField

    StringFieldTest Ilustra las posibilidades de StringField

    Estas aplicaciones se pueden ejecutar por separado o bien a travs de la clase Pruebas que nospermite decidir qu aplicacin ejecutar.

    Los ejemplos de uso son, creo, bastante intuitivos, sin embargo, hay algunos trucos poco evidentes:

    En la aplicacin DNIFieldTest, no hace falta escribir siempre la letra del DNI, si se han

    entrado todos los nmeros del DNI, basta con pulsarCtrl-Espacio y la letra correctaaparecer por arte de magia.Si lo que sucede es que la letra entrada es incorrecta, tambin se puede recurrir aCtrl-Espacio para que se cambie por la correcta.

    En la aplicacin DateFieldTest, despus de especificar un nuevo patrn, podemosactivarlo pulsando el botn OK o bien pulsando intro en el campo de patrn.Tambin es importante tener en cuenta que en el campo Aadir, podemos especificarcantidades negativas para que reste.

    En los ejemplos IntegerFieldTest y DNIFieldTest, la combinacin de teclas, cuando el foco est en el campo, abren un dilogo que muestra el valor delcampo.

    19 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    20/24

    Arquitectura de clases

    La siguiente figura nos muestra el diagrama de clases de los componentes de ejemplo derivados deJformattedTextField. Tngase en cuenta que el diagrama no incluye todos los mtodos.

    20 de 24

    Figura 2: Diagrama de clases de los componentes de ejemplo

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    21/24

    21 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    22/24

    EPLOGOEs notable el aparente cambio de estrategia de Sun proporcionando en la versin 1.4 de Java dosnuevos componentes Swingque intentan cubrir vacos importantes en lo que al desarrollo deinterficies grficas se refiere. Lamentablemente, la versin 5.0 no incluye ningn componente nuevoni mejora los anteriores.

    JFormattedTextField nos permite desarrollar aplicaciones ms profesionales y mejora laimagen de Swing. Tenemos mscaras, campos de fecha con un comportamiento razonable, podemosusar diversos formateadores para personalizar nuestros campos, etc.

    Sin embargo, durante el tiempo que me ha llevado construir este artculo, he encontrado algunosobstculos que me han dificultado la labor de escribir tanto el texto del artculo como loscomponentes de ejemplo.

    He encontrado, y es una opinin personal, problemas de ortogonalidad, algunos de los cuales ya heexpuesto, como la diferencia de comportamiento de commitEdit() y setValue() que,combinados con la admisin o no de literales en el valor del MaskFormatter, me han dado algn

    que otro quebradero de cabeza. En el mismo orden de cosas estara el establecimiento de rangos deInternationalFormatter.

    Siguiendo con la ortogonalidad, me pregunto dnde est el modelde JformattedTextField?Ciertamente, sigue siendo el mismo que el de su padre, JTextField, un PlainDocument. Sinembargo, las relaciones entre vista/controlador (delegate) y modelo, ni son tan claras como enJTextField ni se cuentan en parte alguna.

    Me he encontrado tambin con problemas de visibilidad (scope) cuando he intentado extender, porejemplo, DefaultFormatter. Hay mtodos importantes de DefaultFormatter y deJTextComponent que slo estn visibles a nivel depackage y que dificultan extender tantoDefaultFormatter como AbstractFormatter. Es realmente complejo extender los

    formateadores que nos vienen dados.En el proceso de creacin de este artculo, me propuse reproducir un componente que habadesarrollado hace tiempo como una extensin de JTextField y que ofreca una funcionalidadsencilla pero prctica: determinar el nmero mximo de caracteres que poda aceptar un campo deentrada.

    Ante la dificultad de extenderDefaultFormatter, decid ir directamente a PlainDocumenty atacar el modelo como hice anteriormente. Bien, no acab de funcionar. El mtodoinsertString() de AbstractDocument no se invoca al insertar una tira (por teclado odesde el clipboard) como en JTextField, sino cuando el campo cambia de foco. La falta detiempo y las dificultades han hecho que abandonara esta lnea. Finalmente, y para la versin 1.1 de

    este artculo, he desarrollado StringField, pero recurriendo al control de la propiedad value,ya que las otras vas, a mi entender ms coherentes, han resultado imposibles de seguir(posiblemente por mis limitaciones personales).

    A pesar de los pesares, creo que JFormattedTextField es un componente importante quedebe formar parte, de manera habitual, en nuestras aplicaciones.

    Deseo que el lector pueda, con la ayuda de este artculo, sortear mejor que yo las dificultades decreacin de componentes derivados de JFormattedTextField y que este artculo contribuya ahacer un mejor y mayor uso de Swingen sus aplicaciones de escritorio.

    22 de 24

  • 8/3/2019 Usos Interesantes de JFormattedTextField

    23/24

    QU HE USADO?He usado Eclipse 3.0.1 (http://www.eclipse.org) para el desarrollo, la generacin de Javadocs y las

    pruebas unitarias con JUnit 3.8.1 (http://www.junit.org).

    Para el desarrollo de las interficies de usuario en Swing, he usado el Visual Editorde Eclipse

    (http://www.eclipse.org/vep/) en su versin 1.0.2.1RC2.Para la generacin del diagrama de clases de los componentes, he usado la ltima versin del pluginde Eclipse Omondo EclipseUML (http://www.omondo.com/index.html).

    Este artculo ha sido escrito con OpenOffice 2.0 beta (http://www.openoffice.org/) y ste tambin seha usado para la generacin del PDF.

    QU HE LEDO?Realmente, hay poca literatura que haga referencia a JformattedTextField. Yo slo he

    encontrado un par de tutoriales que cubren los aspectos ms bsicos.El primero, siempre es una referencia, es el captuloHow to Use Formatted Text Fields(http://java.sun.com/docs/books/tutorial/uiswing/components/formattedtextfield.html) del tutorialoficial de Java. Es correcto, pero creo que insuficiente si quieres trabajar a fondo con las

    posibilidades deJformattedTextField. Expone con claridad algunos conceptos bsicos.

    El segundo, es el artculo de John Zukowski Swing's new JFormattedTextField component(http://www-106.ibm.com/developerworks/java/library/j-mer0625/) de junio de 2002 dentro de lainteresante serie de artculos sobre novedades de la versin 1.4 de Java Magic with Merlin que elautor ha publicado en developerWorks. Bien escrito pero muy bsico.

    Como he comentado ms arriba, para entender el funcionamiento de JFormattedTextField,he tenido que leer mucha API y bastante cdigo fuente.

    INSTALACIN, CONTENIDO Y EJECUCINEste tutorial y los archivos relacionados estn empaquetados en un archivo ZIP. Al descomprimirlo(respetando la estructura de directorios) se crear el subdirectorio JFTF que contiene:

    El archivo LEEME.TXT que explica, como aqu, qu contiene el directorio y cmo se usa.

    Este artculo en formato PDF.

    El archivo jftf.jar que contiene los componentes de ejemplo, las aplicaciones dedemostracin y los tests unitarios.

    El subdirectorio src que contiene el cdigo fuente.

    El subdirectorio bin con las classes compiladas.

    El subdirectorio doc que contiene los javadoc de todas las clases.

    Ejecucin de las aplicaciones de ejemplo

    Las aplicaciones de ejemplo se pueden ejecutarse por separado o bien, yo lo recomiendo, ejecutando

    la clase com.froses.jftf.widgets.demo.Pruebas:

    23 de 24

    http://www.eclipse.org/http://www.junit.org/http://www.eclipse.org/vep/http://www.omondo.com/index.htmlhttp://www.openoffice.org/http://java.sun.com/docs/books/tutorial/uiswing/components/formattedtextfield.htmlhttp://www-106.ibm.com/developerworks/java/library/j-mer0625/http://www-106.ibm.com/developerworks/views/java/articles.jsp?sort_order=desc&expand=&sort_by=Date&show_abstract=true&view_by=Search&search_by=merlin:http://www-130.ibm.com/developerworks/http://www.eclipse.org/http://www.junit.org/http://www.eclipse.org/vep/http://www.omondo.com/index.htmlhttp://www.openoffice.org/http://java.sun.com/docs/books/tutorial/uiswing/components/formattedtextfield.htmlhttp://www-106.ibm.com/developerworks/java/library/j-mer0625/http://www-106.ibm.com/developerworks/views/java/articles.jsp?sort_order=desc&expand=&sort_by=Date&show_abstract=true&view_by=Search&search_by=merlin:http://www-130.ibm.com/developerworks/
  • 8/3/2019 Usos Interesantes de JFormattedTextField

    24/24