在DoubleProperty

时间:2016-09-19 18:35:01

标签: java javafx properties

我最近试图将我的双重属性范围限制为(0.0 - 1.0)。超出此范围的变化不会产生任何影响,或引发错误。

目前我用两种方式做到了:

  • 只读,仅允许在加密者上进行更改:

    private ReadOnlyDoubleWrapper numProperty = new ReadOnlyDoubleWrapper(0);
    
    public final double getNum() {
        return numProperty().get();
    }
    
    public final void setNum(double num) {
        if(num < 0)
            num = 0;
        if(num > 1)
            num = 1;
        numProperty.set(num);
    }
    
    public ReadOnlyDoubleProperty numProperty() {
        return numProperty.getReadOnlyProperty();
    }
    
  • 将侦听器设置为重置值:

    private DoubleProperty numProperty = new SimpleDoubleProperty(0);
    numProperty.addListener(new BoundRangeListener(numProperty, 0.0, 1.0));
    
    
    class BoundRangeListener implements ChangeListener<Number> {
    
        Property<Number> prop;
        double min, max;
    
        BoundRangeListener(Property<? extends Number> prop, double min, double max) {
            this.prop = prop;
            this.min = min;
            this.max = max;
        }
    
        public void changed(ObservableValue<? extends Number> o,
                                             Number oldValue, Number newValue) {
            if(newValue.doubleValue() < min)
                prop.set(min);
            if(newValue.doubleValue() > max)
                prop.set(max);
    
            // Optional: throw exception
        }
    
    }
    

尽管如此,我对这些解决方案都不满意。第一个不允许我的用户绑定属性;没有理由,不是我想要的东西。第二个会向其他听众发射2个事件;没有好处。

所以我的问题是:是否有任何开箱即用的方法拒绝更改,或将数字属性绑定到范围?

3 个答案:

答案 0 :(得分:2)

考虑继承SimpleDoubleProperty并重写setsetValue方法:

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;

public class ClampedDoublePropertyTest {

    private DoubleProperty numProperty = new SimpleDoubleProperty(0) {

        @Override
        public void set(double value) {

            System.out.println("set("+value+")");
            if (value < 0) {
                value = 0 ;
            }
            if (value > 1) {
                value = 1 ;
            }
            super.set(value);
        }

        @Override
        public void setValue(Number value) {
            System.out.println("setValue("+value+")");
            if (value == null) {
                // depending on requirements, throw exception, set to default value, etc.
            } else {
                if (value.doubleValue() < 0) {
                    value = new Double(0);
                }
                if (value.doubleValue() > 1) {
                    value = new Double(1);
                }
                super.setValue(value);
            }
        }

    };

    public DoubleProperty numProperty() {
        return numProperty;
    }

    public final double getNum() {
        return numProperty().get();
    }

    public final void setNum(double num) {
        numProperty().set(num);
    }

    public static void main(String[] args) {
        ClampedDoublePropertyTest test = new ClampedDoublePropertyTest();
        test.numProperty().addListener((obs, oldValue, newValue) -> System.out.println(oldValue +" -> "+newValue));

        DoubleProperty value = new SimpleDoubleProperty();
        test.numProperty().bind(value);
        value.set(0.5);
        value.set(2);
        value.set(-5);
    }
}

这将允许客户端代码以通常的方式绑定属性:

myInstance.numProperty().bind(...);

虽然注意到这会违反通常的约束合同,就好像它所绑定的可观察值超出范围,这两个值将不相等。

顺便说一句,FWIW Oracle recommend(幻灯片29)听众的方法,虽然我同意你的看法我不喜欢(特别是因为它允许观察者观察&#34;无效值&#34;)。

答案 1 :(得分:2)

我已经实施了LimitedComparableProperty。也许你发现它很有用。

double minValue = 0;
double maxValue = 1;
LimitedComparableProperty<Double> numProperty = new LimitedComparableProperty<>(this, "numProperty", 0, minValue , maxValue);

注意:目前仅支持Comparable,不支持基本类型。 (你必须使用Double而不是double)。

的Maven:

<dependency>
    <groupId>org.drombler.commons</groupId>
    <artifactId>drombler-commons-fx-core</artifactId>
    <version>0.7</version>
</dependency>

该代码可在GitHub上找到。

答案 2 :(得分:-1)

最简单的方法是做这样的事情:

Math.max(min, Math.min(val, max));

这应该使任何小于最小值(0.0)的数字设置为最小值,并且任何大于最大值(1.0)的数字都应设置为最大值。