Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX 8 Binding with number format

Can someone please show me an example of a Bindings.bindBidirectional where a textfield is bound to a Double value AND the textfield is formatted to zero decimal places. I have this binding:

Bindings.bindBidirectional(xProperty, sp.layoutXProperty(), converter);

where xProperty is a StringProperty and sp.layoutXProperty is a DoubleProperty.

I have tried many different converters and finally settled on:

NumberFormat nf = NumberFormat.getInstance();    
StringConverter<Number> converter = new NumberStringConverter(nf);

Then I tried:

nf.setParseIntegerOnly(true);

But to no avail. This was only one of many attempts at achieving the result. It's probably straight forward, but information on binding different properties with a format seems few and far between or have I missed the obvious?

like image 711
Frank Avatar asked Aug 24 '15 02:08

Frank


2 Answers

Look at this code and see if it solves your problem:

public class BindingTest {
    static Property<String> sp;
    static Property<Double> dp;

    public static void main(String[] args) {
        sp = new SimpleStringProperty();
        dp = new SimpleObjectProperty<>();

        StringConverter<Double> sc = new StringConverter<Double>() {
            @Override
            public String toString(Double object) {
                if (object != null)
                    return Integer.toString((int) Math.round(object.doubleValue()));
                else
                    return null;
            }

            @Override
            public Double fromString(String string) {
                Double d = Double.parseDouble(string);
                sp.setValue(Integer.toString((int) Math.round(d)));
                return d;
            }
        };

        Bindings.bindBidirectional(sp, dp, sc);

        print();
        sp.setValue("3.14");
        print();
        dp.setValue(6.18);
        print();
    }

    public static void print() {
        System.out.println("String: " + sp.getValue() + "\t" + "Double: " + dp.getValue());
    }
}

Output:

String: null    Double: null
String: 3   Double: 3.14
String: 6   Double: 6.18
like image 94
Mehran Avatar answered Sep 28 '22 10:09

Mehran


There maybe different approaches converting double value to integer, which use different roundings while converting. This answer is similar to others, with an additional filter that allows only integer values in text field:

@Override
public void start( Stage stage )
{
    TextField field = new TextField();
    DoubleProperty doubleProperty = new SimpleDoubleProperty();
    Label label = new Label();
    label.textProperty().bind( doubleProperty.asString() );

    DecimalFormat format = new DecimalFormat();
    format.setParseIntegerOnly( true );  // used while parsing the input text of textfield
    format.setMaximumFractionDigits( 0 );  // used while formatting the doubleProperty's bound value as output text of textfield
    format.setGroupingUsed( false );  // disable thousand grouping
    format.setRoundingMode( RoundingMode.UP );  // set rounding mode

    Bindings.bindBidirectional( field.textProperty(), doubleProperty, new StringConverter<Number>()
    {
        @Override
        public String toString( Number object )
        {
            return object == null ? "" : format.format( object );
        }


        @Override
        public Number fromString( String string )
        {
            return (string != null && !string.isEmpty()) ? Double.valueOf( string ) : null;
        }
    } );

    // apply filter to allow only integer values
    field.setTextFormatter( new TextFormatter<>( c ->
    {
        if ( c.getControlNewText().isEmpty() )
        {
            return c;
        }

        ParsePosition parsePosition = new ParsePosition( 0 );
        Object object = format.parse( c.getControlNewText(), parsePosition );

        if ( object == null || parsePosition.getIndex() < c.getControlNewText().length() )
        {
            return null;
        }
        else
        {
            return c;
        }

    } ) );

    Button b = new Button( "+1.6" );
    b.setOnAction( ( e ) ->
    {
        doubleProperty.set( doubleProperty.get() + 1.6 );
    } );

    Scene scene = new Scene( new VBox( 5 ) );
    stage.setWidth( 450 );
    stage.setHeight( 250 );
    (( VBox ) scene.getRoot()).getChildren().addAll( field, label, b );
    stage.setScene( scene );
    stage.show();
}
like image 43
Uluk Biy Avatar answered Sep 28 '22 09:09

Uluk Biy