我想有一个属性total是由两个属性相乘,即获得currentPrice和volumeHeld,在currentPrice实际上是通过下载谷歌财经的股票价格,每10秒获得.它每10秒自动更新一次.
现在getCurrentPrice()初始化为0,如代码所示.10秒后,它获得了一个新值,这一切都正常.
但是在下面的绑定方法中,属性更改total时不会自动更新currentPrice.
totalBinding = Bindings.createDoubleBinding(() -> {
System.out.println("current price: " + getCurrentPrice() + "vol held: " + getVolumeHeld());
return getCurrentPrice() * getVolumeHeld();
});
total.bind(totalBinding);
Run Code Online (Sandbox Code Playgroud)
问题:我发现在createDoubleBinding上面的语句中,其getCurrentPrice()值为0(如上所述),并且当其值更改时,更改不会在total属性中传播.我的意思total是,getCurrentPrice()即使当前价格发生变化,房产也无法从中获取新价值.
所以问题是双重的,但我猜我下面的两个问题的解决方案将是相似的,如果不完全相同:
我该如何解决上述问题?
Later on, I will be binding this total property to another property to work out the total of the total property for all Trade objects). This fails miserably and it is always equal to 0. This method is written in a different class, i.e. not in the Trade class.
UPDATE:
Code shown below:
class SummaryofTrade{
...
sumOfTotals = new ReadOnlyDoubleWrapper();
sumOfTotalsBinding = Bindings.createDoubleBinding(() -> {
double sum = 0;
for(Trade t : this.observableListOfTrades){
sum += t.getTotal();
}
return sum;
}, total); // I cannot put "total" as a second parameter, as it is a property that resides in the Trade class , not this class.
sumOfTotals.bind(sumOfTotalsBinding);
...
}
Run Code Online (Sandbox Code Playgroud)
The error log message:
Caused by: java.lang.Error: Unresolved compilation problem:
total cannot be resolved to a variable
Run Code Online (Sandbox Code Playgroud)
Please note that the sumOfTotalsBinding and sumOfTotals live in another class.
Code for Trade object below:
class Trade{
...
private final ReadOnlyDoubleWrapper total;
private final ReadOnlyDoubleWrapper currentPrice;
private DoubleProperty volumeHeld;
public DoubleBinding totalBinding;
private final ScheduledService<Number> priceService = new ScheduledService<Number>() {
@Override
public Task<Number> createTask(){
return new Task<Number>() {
@Override
public Number call() throws InterruptedException, IOException {
return getCurrentPriceFromGoogle();
}
};
}
};
public Trade(){
...
priceService.setPeriod(Duration.seconds(10));
priceService.setOnFailed(e -> priceService.getException().printStackTrace());
this.currentPrice = new ReadOnlyDoubleWrapper(0);
this.currentPrice.bind(priceService.lastValueProperty());
startMonitoring();
this.total = new ReadOnlyDoubleWrapper();
DoubleBinding totalBinding = Bindings.createDoubleBinding(() ->
getCurrentPrice() * getVolumeHeld(),
currentPriceProperty(), volumeHeldProperty());
total.bind(totalBinding);
}
// volume held
public double getVolumeHeld(){
return this.volumeHeld.get();
}
public DoubleProperty volumeHeldProperty(){
return this.volumeHeld;
}
public void setVolumeHeld(double volumeHeld){
this.volumeHeld.set(volumeHeld);
}
// multi-threading
public final void startMonitoring() {
priceService.restart();
}
public final void stopMonitoring() {
priceService.cancel();
}
public ReadOnlyDoubleProperty currentPriceProperty(){
return this.currentPrice.getReadOnlyProperty();
}
public final double getCurrentPrice(){
return currentPriceProperty().get();
}
// total
public final Double getTotal(){
return totalProperty().getValue();
}
public ReadOnlyDoubleProperty totalProperty(){
return this.total;
}
}
Run Code Online (Sandbox Code Playgroud)
UPDATE 9/15/2015:
I am trying to elaborate my problem in a logical way here. Let me know if this does not make sense. Thanks.
First, in the Trade class above (please note the code above has been updated and specified the property dependency), each Trade object contains a total property, which is the product of currentPrice and VolumeHeld. If the user manually edit the values of current price and volume held. The total property will be updated automatically.
Now, I have an ObservableList of Trade objects, each of them has a total property. My goal is to sum up the the total property of each Trade object in the observable list and bind the sum to a variable called sumOfTotals. This is done in a class called SummaryOfTrade. And whenever the total property of any one of the Trades in the Observable list changes, the sumOfTotals property should also change automatically.
class SummaryofTrade{
...
// within constructor, we have
sumOfTotals = new ReadOnlyDoubleWrapper();
sumOfTotalsBinding = Bindings.createDoubleBinding(() -> {
double sum = 0;
for(Trade t : this.observableListOfTrades){
sum += t.getTotal();
}
return sum;
}, totalProperty());
sumOfTotals.bind(sumOfTotalsBinding);
...
}
Run Code Online (Sandbox Code Playgroud)
This is where the problem comes in. Eclipse is saying that it does not recognise the Trade object's property,totalProperty. Error message shown below.
The error log message:
Caused by: java.lang.Error: Unresolved compilation problem:
The method totalProperty() is undefined for the type SummaryOfTrade
Run Code Online (Sandbox Code Playgroud)
I have specified the property dependency already yet Eclipse is throwing an error. How should I resolve this?
由于当前价格和交易量都是属性,您可以直接绑定它们:
total.bind(currentPriceProperty().multiply(volumeHeldProperty()));
Run Code Online (Sandbox Code Playgroud)
如果您绝对需要使用自定义双重绑定,则首先需要提供依赖项,以便在依赖项根据文档失效时执行计算:
DoubleBinding totalBinding = new DoubleBinding() {
{
super.bind(currentPrice, volumeHeld);
}
@Override
protected double computeValue() {
return currentPrice.get() * volumeHeld.get();
}
};
Run Code Online (Sandbox Code Playgroud)
提供的以下辅助函数Bindings也应该起作用:
DoubleBinding totalBinding = Bindings.createDoubleBinding(() ->
currentPrice.get() * volumeHeld.get(),
currentPrice, volumeHeld);
Run Code Online (Sandbox Code Playgroud)