gpt4 book ai didi

java - 在 JavaFX 中使用 ObjectBinding 进行双向绑定(bind)

转载 作者:太空狗 更新时间:2023-10-29 22:57:25 24 4
gpt4 key购买 nike

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

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;
}
}

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

最佳答案

您将需要监听字段的变化,但要跟踪监听器是否已被触发,以免在无休止的循环中再次触发。灵感来自 JavaFX 的实际代码,已反编译 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;
}
}
}
});
}

这既简单又繁琐;如果您广泛使用此功能,则可以将内部 ChangeListener 重构为某种常见类型或其他一些巧妙的解决方案。

我用下面的 main 测试了上面的代码(你必须提供一个 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() + "%");
}

关于java - 在 JavaFX 中使用 ObjectBinding 进行双向绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20703544/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com