Bidirectional binding with ObjectBinding in JavaFX

前端 未结 1 568
我在风中等你
我在风中等你 2020-12-16 14:43

I have a simple bean that has some properties related with each other. For example, this bean has a property called discountRate and another called

相关标签:
1条回答
  • 2020-12-16 15:18

    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 ChangeListeners 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() + "%");
    }
    
    0 讨论(0)
提交回复
热议问题