JavaFX中的ObjectBinding进行双向绑定

我有一个简单的Bean,它具有彼此相关的某些属性。例如,此bean具有一个名为 的属性和另一个名为

的属性。DiscountRate是应用于销售的折扣百分比(%)。discountValue是应用于销售的折扣值($)。由于用户可以告知百分比或值,而且我需要将两个值存储在数据库中,因此JavaFX双向绑定可以解决此问题,但是,正如您可以想象的那样,这些值是相关的,但并不相同。我尝试解决此问题,在两侧创建绑定:

public class ExampleBean{

private ObjectProperty<BigDecimal> discountValue;

private ObjectProperty<BigDecimal> discountRate;

public BigDecimal getDiscountvalue() {

return discountValueProperty().getValue();

}

public void setDiscountValue(BigDecimal discountvalue) {

this.discountValueProperty().set(discountvalue);

}

public ObjectProperty<BigDecimal> discountValueProperty() {

if(discountValue==null){

discountValue=new SimpleObjectProperty<BigDecimal>(new BigDecimal("0.00"));

discountRate=new SimpleObjectProperty<BigDecimal>(new BigDecimal("0.00"));

configureDiscountBinding();

}

return discountValue;

}

private void configureDiscountBinding(){

discountValue.bind(Bindings.createObjectBinding(new Callable<BigDecimal>() {

@Override

public BigDecimal call() throws Exception {

return getDiscountRate().multiply(getTotalValue()).divide(new BigDecimal("100"));

}

}, discountRateProperty()));

discountRate.bind(Bindings.createObjectBinding(new Callable<BigDecimal>() {

@Override

public BigDecimal call() throws Exception {

return getDiscountValue().multiply(new BigDecimal("100")).divide(getTotalValue());

}

}, discountValueProperty()));

}

public BigDecimal getDiscountRate() {

return discountRateProperty().getValue();

}

public void setDiscountRate(BigDecimal discountRate) {

this.discountRateProperty().set(discountRate);

}

public ObjectProperty<BigDecimal> discountRateProperty() {

if(discountRate==null){

discountRate=new SimpleObjectProperty<BigDecimal>(new BigDecimal("0.00"));

discountValue=new SimpleObjectProperty<BigDecimal>(new BigDecimal("0.00"));

configureDiscountBinding();

}

return discountRate;

}

}

如您所见,我正在尝试在设置值时计算百分比,并在设置费率时计算值。我上面尝试的绑定无法绑定,因为它将进入一个永恒的循环。有没有一种方法可以绑定以解决此问题,或者我需要在setter中进行计算?

回答:

您将需要侦听对字段的更改,但是要跟踪是否触发了侦听器,以免在无休止的循环中再次触发。灵感来自JavaFX的实际代码,在此进行了反编译。

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;

}

}

}

});

}

这既简单又麻烦;如果您广泛使用此功能,则可以将inner重构ChangeListener为某种常见类型或其他一些聪明的解决方案。

我用以下主要代码测试了上面的代码(您将不得不提供一个BigDecimal

getTotalValue()方法,就我而言,我只是返回了一个常量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() + "%");

}

以上是 JavaFX中的ObjectBinding进行双向绑定 的全部内容, 来源链接: utcz.com/qa/421909.html

回到顶部