views:

155

answers:

1

I need to make custom text field which will format numeric values according to local way of formatting. So I've made a clas:

public class NumberTextField extends JFormattedTextField 
{...

constructor looks this like:

  public NumberTextField()
   {

    formater=new NumberFormatter();
    formater.setAllowsInvalid( false );
    nf=NumberFormat.getInstance();
    formater.setFormat( nf );

    this.setFormatter( formater );    
   }

It ends up with:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot format given Object as a Number
    at java.text.DecimalFormat.format(Unknown Source)
    at java.text.Format.format(Unknown Source)
    at javax.swing.text.InternationalFormatter.valueToString(Unknown Source)
    at javax.swing.JFormattedTextField$AbstractFormatter.install(Unknown Source)
    at javax.swing.text.DefaultFormatter.install(Unknown Source)
    at javax.swing.text.InternationalFormatter.install(Unknown Source)
    at javax.swing.JFormattedTextField.setFormatter(Unknown Source)
    at hr.ikb.nasa.gui.custom.NumberTextField.<init>(NumberTextField.java:65)
    at hr.ikb.nasa.gui.custom.NumberTextField.main(NumberTextField.java:35)

Since google could not offer something usefull I wanted to see what can you say about it. Maybe it has no value to cope with - I tried to put in constructor this.setValue(new Double(0.0d)); or this.setText("0"); - it did not help..

+1  A: 

(Per my comment below): Sub-classing JFormattedTextField and calling the protected setFormat method is probably not the correct approach. From the API docs:

"You should not normally invoke this, instead set the AbstractFormatterFactory or set the value."

Instead I would recommend not sub-classing JFormattedTextField but rather create one using the JFormattedTextField(AbstractFormatter) constructor. I'll leave the code from my original response below in case it's useful - I typically use this formatter when the input of a numerical value is optional and hence a blank text field should imply null.

public class BlankAsNullNumberFormatter extends NumberFormatter {
    private static final long serialVersionUID = 5867546077017490042L;

    public BlankAsNullNumberFormatter(Class<? extends Number> numberKlazz) {
        setValueClass(numberKlazz);
    }

    public BlankAsNullNumberFormatter(Class<? extends Number> numberKlazz, NumberFormat format) {
        super(format);
        setValueClass(numberKlazz);
    }

    public String valueToString(Object iv) throws ParseException {
        if (iv == null) {
            return "";
        } else {
            return super.valueToString(iv);
        }
    }

    public Object stringToValue(String text) throws ParseException {
        if ("".equals(text)) {
            return null;
        }

        return super.stringToValue(text);
    }
}
Adamski
nope... tried your code, copy-pasted it, and still the same error. Instantiated it with BlankAsNullNumberFormatter(Class<? extends Number> numberKlazz) so actually I do not know if it has format at all, will try to check that also..
ante.sabo
I don't think you should be sub-classing JFormattedTextField and calling the protected setFormatter method. Instead try creating a JFormattedTextField using the JFormattedTextField(JFormattedTextField.AbstractFormatter) constructor.
Adamski
well... how to use factory if this is to be GUI widget that should be drag-n-dropped from palette onto form. People drawing forms should not have much experience with hand coding, everything must be form related.. and matisse form builder uses new() for such things.
ante.sabo