我想拥有一个属性 total
这是通过将两个属性相乘得到的,即 currentPrice
和 volumeHeld
, 其中currentPrice
实际上是通过每 10 秒下载 google finance 股票价格获得的。它每 10 秒自动更新一次。
现在 getCurrentPrice()
在 0
初始化,如代码所示。 10 秒后,它获得了一个新值,一切正常。
但是在下面的绑定(bind)方法中,total
currentPrice
时不会自动更新属性(property)发生了变化。
totalBinding = Bindings.createDoubleBinding(() -> {
System.out.println("current price: " + getCurrentPrice() + "vol held: " + getVolumeHeld());
return getCurrentPrice() * getVolumeHeld();
});
total.bind(totalBinding);
问题:我发现在 createDoubleBinding
中上面的语句,getCurrentPrice()
值为 0(如上所述),当其值更改时,更改不会在 total
中传播属性(property)。我的意思是 total
属性无法从 getCurrentPrice()
中获取新值即使当前价格发生变化。
所以问题是双重的,但我猜下面两个问题的解决方案即使不完全相同也会相似:
如何解决上述问题?
稍后,我将绑定(bind)此
total
属性(property)到另一个属性(property)计算出总数total
所有人的属性(property)Trade
对象)。这失败得很惨,它总是等于 0。这个方法是在不同的类中编写的,即不在 Trade 类中。
更新:
代码如下:
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);
...
}
错误日志信息:
Caused by: java.lang.Error: Unresolved compilation problem:
total cannot be resolved to a variable
请注意 sumOfTotalsBinding
和 sumOfTotals
住在另一个类(class)。
下面的贸易对象代码:
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;
}
}
2015 年 9 月 15 日更新:
我试图在这里以合乎逻辑的方式阐述我的问题。如果这没有意义,请告诉我。谢谢。
首先,在 Trade class
上面(请注意上面的代码已经更新并且指定了属性依赖),每个 Trade 对象包含一个 total
属性(property),这是currentPrice
的产品和 VolumeHeld
.如果用户手动编辑当前价格和持有量的值。 total
属性将自动更新。
现在,我有一个 Trade 对象的 ObservableList,每个对象都有一个 total
属性(property)。我的目标是总结 total
可观察列表中每个 Trade 对象的属性,并将总和绑定(bind)到名为 sumOfTotals
的变量.这是在一个名为 SummaryOfTrade
的类中完成的.每当 total
Observable 列表中任何一项交易的属性发生变化时,sumOfTotals
属性也应该自动更改。
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);
...
}
这就是问题所在。Eclipse 说它无法识别 Trade 对象的属性 totalProperty
.错误信息如下所示。
错误日志信息:
Caused by: java.lang.Error: Unresolved compilation problem:
The method totalProperty() is undefined for the type SummaryOfTrade
我已经指定了属性依赖关系,但 Eclipse 抛出错误。我该如何解决?
最佳答案
由于当前价格和持有量都是属性,您可以直接绑定(bind)它们:
total.bind(currentPriceProperty().multiply(volumeHeldProperty()));
如果您绝对需要使用自定义双重绑定(bind),您首先需要提供依赖项,以便在依赖项根据 documentation 失效后执行计算。 :
DoubleBinding totalBinding = new DoubleBinding() {
{
super.bind(currentPrice, volumeHeld);
}
@Override
protected double computeValue() {
return currentPrice.get() * volumeHeld.get();
}
};
Bindings
提供的以下辅助函数也应该有效:
DoubleBinding totalBinding = Bindings.createDoubleBinding(() ->
currentPrice.get() * volumeHeld.get(),
currentPrice, volumeHeld);
关于javafx:绑定(bind)未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32536096/