代码之家  ›  专栏  ›  技术社区  ›  Robert K

JavaFX 8绑定。时间和绑定。“除以”创建“除以零”

  •  3
  • Robert K  · 技术社区  · 6 年前

    我正在为绑定而挣扎。什么时候我试图创建一个百分比分数,当成功测试的数量发生变化(在下面的代码中反映为“successCountProperty”)或测试的总数发生变化(在“results”的sizeProperty中反映)时,该分数会更新。当我执行这段代码时,我得到了java。lang.ArithmeticException:/by零。当我最初遇到异常时,我找到了绑定。当()。然后()。否则()。不幸的是,在执行此代码时,“then”仍在执行,尽管“when”返回false。有人能帮忙吗?

    public void foo()
    {
        DoubleProperty scoreProperty = new SimpleDoubleProperty(0);
        ListProperty<String> results = new SimpleListProperty<>(FXCollections.observableArrayList());
    
        IntegerProperty successCountProperty = new SimpleIntegerProperty(0);
    
        scoreProperty.bind(Bindings.when(results.sizeProperty().greaterThan(0))
                .then(Bindings.divide(successCountProperty, results.sizeProperty())).otherwise(0));
    }
    
    2 回复  |  直到 6 年前
        1
  •  5
  •   fabian    6 年前

    使用 Bindings 或者,属性本身很容易变得难以阅读和维护。

    在这种情况下,我建议创建 DoubleBinding 使用自定义评估方法:

    scoreProperty.bind(Bindings.createDoubleBinding(() -> {
        int size = results.size();
        return size == 0 ? 0d : ((double) successCountProperty.get()) / size;
    }, results.sizeProperty(), successCountProperty));
    
        2
  •  0
  •   Michael    6 年前

    你的问题是

    Bindings.divide(successCountProperty, results.sizeProperty())
    

    立即进行评估,您似乎期望 lazy evaluation

    您可以编写自己的延迟除法器,该除法器仅在实际查询值时进行除法:

    class LazyDivision extends DoubleBinding
    {
        private IntegerProperty dividend;
        private ReadOnlyIntegerProperty divisor;
    
        LazyDivision(final IntegerProperty dividend, final ReadOnlyIntegerProperty divisor)
        {
            this.dividend = dividend;
            this.divisor = divisor;
        }
    
        @Override
        protected double computeValue()
        {
            return dividend.getValue() / divisor.getValue().doubleValue();
        }
    }
    

    然后像这样使用:

    scoreProperty.bind(
        Bindings
            .when(results.sizeProperty().greaterThan(0))
            .then(
                new LazyDivision(successCountProperty, results.sizeProperty())
            )
            .otherwise(0)
    );