You will need to listen to changes to the fields but keep track if the listener has been fired, so as not to fire again in endless loops. Inspiration was the actual code from JavaFX, decompiled here.
private void configureDiscountBinding() {
discountValue.addListener(new ChangeListener<BigDecimal>() {
private boolean changing;
@Override public void changed(ObservableValue<? extends BigDecimal> observable, BigDecimal oldValue, BigDecimal newValue) {
if( !changing ) {
try {
changing = true;
discountRate.set(newValue.multiply(new BigDecimal("100")).divide(getTotalValue(), RoundingMode.HALF_DOWN));
}
finally {
changing = false;
}
}
}
});
discountRate.addListener(new ChangeListener<BigDecimal>() {
private boolean changing;
@Override public void changed(ObservableValue<? extends BigDecimal> observable, BigDecimal oldValue, BigDecimal newValue) {
if( !changing ) {
try {
changing = true;
discountValue.set(newValue.multiply(getTotalValue()).divide(new BigDecimal("100"), RoundingMode.HALF_DOWN));
}
finally {
changing = false;
}
}
}
});
}
This is simplistic and cumbersome; if you are using this feature extensively, you could refactor the inner ChangeListener
s to some common type, or some other clever solution.
I tested the code above with the following main (you wil have to provide a BigDecimal getTotalValue()
method, in my case I just returned a constant BigDecimal
):
public static void main(String[] args) {
ExampleBean e = new ExampleBean();
System.out.println("Setting rate to 50%");
e.discountRateProperty().set(new BigDecimal(50.0));
System.out.println("-> value=" + e.getDiscountvalue());
System.out.println("Setting value to 25");
e.discountValueProperty().set(new BigDecimal(25.0));
System.out.println("-> rate=" + e.getDiscountRate() + "%");
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…