JavaFx 8 双向绑定
JavaFx 8 Bidirectional binding
以下代码会触发 java.lang.RuntimeException: A bound value cannot be set
:
public class Test {
public static void main( String[] args ) {
final DoubleProperty amount = new SimpleDoubleProperty( 100_000.00 );
final DoubleProperty rate = new SimpleDoubleProperty();
final DoubleProperty part = new SimpleDoubleProperty();
rate.bind( part.divide ( amount.getValue()));
part.bind( rate.multiply( amount.getValue()));
rate.set( 0.025 );//<<----------------------------------- Here is the cause
System.out.println( "Part: " + part.get());
part.set( 1200 );
System.out.println( "Rate: " + rate.get());
}
}
使用 Bindings.bindBidirectional 可能是一个解决方案,但我不知道如何解决。
一个简单的静态方法,一个自制的NumberBiBinding
完成工作:
public final class NumberBiBinding {
public static void bind(
Property<Number> operand1,
NumberBinding operator1,
Property<Number> operand2,
NumberBinding operator2 )
{
assert operand1 != operand2;
operand1.addListener( o -> operand2.setValue( operator1.getValue()));
operand2.addListener( o -> operand1.setValue( operator2.getValue()));
}
}
public final class Test {
public static void main( String[] args ) {
final DoubleProperty amount = new SimpleDoubleProperty( 100_000.00 );
final DoubleProperty rate = new SimpleDoubleProperty();
final DoubleProperty part = new SimpleDoubleProperty();
NumberBiBinding.bind(
rate, rate.multiply( amount ),
part, part.divide ( amount ));
System.out.println( "Amount: " + amount.get());
rate.set( 0.025 );
System.out.println(
"Part is " + part.get() + " when rate is set to " + rate.get());
part.set( 1200 );
System.out.println(
"Rate is " + rate.get() + " when part is set to " + part.get());
}
}
输出:
Amount: 100000.0
Part is 2500.0 when rate is set to 0.025
Rate is 0.012 when part is set to 1200.0
一个可能的解决方案是创建 InvalidationListeners - 不使用绑定。
工作原理:
- 设置费率导致费率无效。这是设置部分的时间,因此也是无效的。
- 依次设置速率不会再次触发 InvalidationListener。这就是它的定义方式。
.
public static void main(String[] args) {
final DoubleProperty amount = new SimpleDoubleProperty(100_000.00);
final DoubleProperty part = new SimpleDoubleProperty();
final DoubleProperty rate = new SimpleDoubleProperty();
part.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
System.out.println("part is invalid");
rate.set(part.get() / amount.get());
}
});
rate.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
System.out.println("rate is invalid");
part.set(rate.get() * amount.get());
}
});
System.out.println("setting rate");
rate.set(0.025);
System.out.println("Part: " + part.get()); //2500
System.out.println("setting part");
part.set(1200);
System.out.println("Rate: " + rate.get()); //0.012
}
上面代码的输出是:
setting rate
rate is invalid
part is invalid
Part: 2500.0
setting part
part is invalid
rate is invalid
Rate: 0.012
以下代码会触发 java.lang.RuntimeException: A bound value cannot be set
:
public class Test {
public static void main( String[] args ) {
final DoubleProperty amount = new SimpleDoubleProperty( 100_000.00 );
final DoubleProperty rate = new SimpleDoubleProperty();
final DoubleProperty part = new SimpleDoubleProperty();
rate.bind( part.divide ( amount.getValue()));
part.bind( rate.multiply( amount.getValue()));
rate.set( 0.025 );//<<----------------------------------- Here is the cause
System.out.println( "Part: " + part.get());
part.set( 1200 );
System.out.println( "Rate: " + rate.get());
}
}
使用 Bindings.bindBidirectional 可能是一个解决方案,但我不知道如何解决。
一个简单的静态方法,一个自制的NumberBiBinding
完成工作:
public final class NumberBiBinding {
public static void bind(
Property<Number> operand1,
NumberBinding operator1,
Property<Number> operand2,
NumberBinding operator2 )
{
assert operand1 != operand2;
operand1.addListener( o -> operand2.setValue( operator1.getValue()));
operand2.addListener( o -> operand1.setValue( operator2.getValue()));
}
}
public final class Test {
public static void main( String[] args ) {
final DoubleProperty amount = new SimpleDoubleProperty( 100_000.00 );
final DoubleProperty rate = new SimpleDoubleProperty();
final DoubleProperty part = new SimpleDoubleProperty();
NumberBiBinding.bind(
rate, rate.multiply( amount ),
part, part.divide ( amount ));
System.out.println( "Amount: " + amount.get());
rate.set( 0.025 );
System.out.println(
"Part is " + part.get() + " when rate is set to " + rate.get());
part.set( 1200 );
System.out.println(
"Rate is " + rate.get() + " when part is set to " + part.get());
}
}
输出:
Amount: 100000.0
Part is 2500.0 when rate is set to 0.025
Rate is 0.012 when part is set to 1200.0
一个可能的解决方案是创建 InvalidationListeners - 不使用绑定。
工作原理:
- 设置费率导致费率无效。这是设置部分的时间,因此也是无效的。
- 依次设置速率不会再次触发 InvalidationListener。这就是它的定义方式。
.
public static void main(String[] args) {
final DoubleProperty amount = new SimpleDoubleProperty(100_000.00);
final DoubleProperty part = new SimpleDoubleProperty();
final DoubleProperty rate = new SimpleDoubleProperty();
part.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
System.out.println("part is invalid");
rate.set(part.get() / amount.get());
}
});
rate.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
System.out.println("rate is invalid");
part.set(rate.get() * amount.get());
}
});
System.out.println("setting rate");
rate.set(0.025);
System.out.println("Part: " + part.get()); //2500
System.out.println("setting part");
part.set(1200);
System.out.println("Rate: " + rate.get()); //0.012
}
上面代码的输出是:
setting rate
rate is invalid
part is invalid
Part: 2500.0
setting part
part is invalid
rate is invalid
Rate: 0.012