我正在尝试实现一个GUI,涉及两个字段的计算。我的模型有两个属性和一个绑定。
ObjectProperty<BigDecimal> price = new SimpleObjectProperty<>();
ObjectProperty<BigDecimal> quantity= new SimpleObjectProperty<>();
ObjectBinding<BigDecimal> totalPrice = new ObjectBinding<BigDecimal>() {
{ bind(price,quantity);}
protected BigDecimal computeValue() {
if (price.get() == null || quantity.get() == null) return null;
return price.get().multiply(quantity.get());
}
};我的图形用户界面有3 TextField来匹配价格,数量,totalPrice。通常,我在我的属性和我的TextField之间做一个规则的绑定
priceTextField.textProperty().bindBidirectional(myModel.priceProperty(), new NumberStringConverter());现在它变得有点棘手。如果用户修改了价格或数量,就会接触到TotalPrice (这是绑定到目前为止所做的)。但是我希望能够这样做:如果用户更新了TotalPrice,那么它会根据固定价格重新计算数量。
因此,问题是:如何创建这样一个流程=> TotalPrice是在价格和数量上绑定的,而数量是绑定在TotalPrice和价格上的。当我在totalPriceTextfield中输入某些内容时,它应该更新quantityTextField,反之亦然。
谢谢。
*编辑*这里有一段丑陋的代码来说明我想要实现的目标(nb:我知道我可以使用Binding.multiply和其他方法,但是我需要将来的项目来实现计算函数)
public class TestOnBindings {
private DoubleProperty price = new SimpleDoubleProperty(10.0);
private DoubleProperty quantity = new SimpleDoubleProperty(1.0);
private DoubleProperty total = new SimpleDoubleProperty(1.0);
private DoubleBinding totalBinding = new DoubleBinding() {
{bind(quantity,price);}
@Override
protected double computeValue() {
return quantity.get()*price.get();
}
};
private DoubleBinding quantityBinding = new DoubleBinding() {
{bind(total,price);}
@Override
protected double computeValue() {
return total.get()/price.get();
}
};
public TestOnBindings(){
total.bind(totalBinding); //should really not do that, looks ugly
quantity.bind(quantityBinding); //now you're asking for troubles
}
public void setPrice(Double price){
this.price.set(price);
}
public void setQuantity(Double quantity){
this.quantity.set(quantity);
}
public void setTotal(Double total){
this.total.set(total);
}
public Double getTotal(){
return total.get();
}
public Double getQuantity(){
return quantity.get();
}
public static void main(String[] args) {
TestOnBindings test = new TestOnBindings();
test.setQuantity(5.0);
System.out.println("Total amount = " + test.getTotal());
}
}最明显的错误是:
线程“主”java.lang.RuntimeException中的异常:无法设置绑定值。在javafx.beans.property.DoublePropertyBase.set(DoublePropertyBase.java:142)
发布于 2014-11-21 04:12:02
我想我的问题已经在另一个帖子中得到了回答,这个家伙在他的博客上提供了一个简单的方法
我修改了一些他的类,以适应我的需求,并且有一个非常容易使用的类:
public class CustomBinding {
public static <A ,B> void bindBidirectional(Property<A> propertyA, Property<B> propertyB, Function<A,B> updateB, Function<B,A> updateA){
addFlaggedChangeListener(propertyA, propertyB, updateB);
addFlaggedChangeListener(propertyB, propertyA, updateA);
}
public static <A ,B> void bind(Property<A> propertyA, Property<B> propertyB, Function<A,B> updateB){
addFlaggedChangeListener(propertyA, propertyB, updateB);
}
private static <X,Y> void addFlaggedChangeListener(ObservableValue<X> propertyX, WritableValue<Y> propertyY, Function<X,Y> updateY){
propertyX.addListener(new ChangeListener<X>() {
private boolean alreadyCalled = false;
@Override
public void changed(ObservableValue<? extends X> observable, X oldValue, X newValue) {
if(alreadyCalled) return;
try {
alreadyCalled = true;
propertyY.setValue(updateY.apply(newValue));
}
finally {alreadyCalled = false; }
}
});
}
}然后把它应用到我的例子..。仍然需要一点微调,但它做的工作。
public class TestOnBindings {
private DoubleProperty price = new SimpleDoubleProperty(10.0);
private DoubleProperty quantity = new SimpleDoubleProperty(1.0);
private DoubleProperty total = new SimpleDoubleProperty(1.0);
public TestOnBindings(){
CustomBinding.<Number,Number>bindBidirectional(quantity, total,
(newQuantity)-> newQuantity.doubleValue() * price.get(),
(newTotal)-> newTotal.doubleValue() /price.get());
CustomBinding.<Number,Number>bind(price, total,
(newPrice)-> newPrice.doubleValue() * quantity.get());
}
public void setPrice(Double price){this.price.set(price);}
public void setQuantity(Double quantity){this.quantity.set(quantity);}
public void setTotal(Double total){this.total.set(total);}
public Double getTotal(){return total.get();}
public Double getQuantity(){return quantity.get();}
public Double getPrice(){return price.get();}
public static void main(String[] args) {
TestOnBindings test = new TestOnBindings();
test.setQuantity(5.0);
System.out.println("Quantity = " + test.getQuantity());
System.out.println("Price = " + test.getPrice());
System.out.println("Total = " + test.getTotal());
test.setTotal(60.0);
System.out.println("---------------------------------------------");
System.out.println("Quantity = " + test.getQuantity());
System.out.println("Price = " + test.getPrice());
System.out.println("Total = " + test.getTotal());
test.setPrice(5.0);
System.out.println("---------------------------------------------");
System.out.println("Quantity = " + test.getQuantity());
System.out.println("Price = " + test.getPrice());
System.out.println("Total = " + test.getTotal());
}
}发布于 2014-11-21 03:45:19
你真的要用绑定吗?这样就能完成任务了。总之,绑定只是花哨的侦听器。
public TestOnBindings(){
price.addListener((obs,ov,nv) -> {
total.set(price.doubleValue()*quantity.doubleValue());
});
//could be same listener as price if total is a complicated function
quantity.addListener((obs,ov,nv) -> {
total.set(price.doubleValue()*quantity.doubleValue());
});
total.addListener((obs,ov,nv) -> {
quantity.set(total.doubleValue()/price.doubleValue());
});
}https://stackoverflow.com/questions/27052927
复制相似问题