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?
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
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With