我最近试图将我的双重属性范围限制为(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个事件;没有好处。
所以我的问题是:是否有任何开箱即用的方法拒绝更改,或将数字属性绑定到范围?
答案 0 :(得分:2)
考虑继承SimpleDoubleProperty
并重写set
和setValue
方法:
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)的数字都应设置为最大值。