Issue
I'm trying to create a binding of a list of LineItem
's amounts with the following line:
ReadOnlyObjectWrapper<BigDecimal> total = new ReadOnlyObjectWrapper<>();
total.bind(Bindings.createObjectBinding(() -> items.stream()
.collect(Collectors.summingDouble(LineItem::getTotal)),
items));
Obviously, the Collectors.summingDouble
won't work as it's a BigDecimal
. Is there any way to do this with a BigDecimal?
LineItem.java
public class LineItem
{
private final SimpleObjectProperty<BigDecimal> amount;
public LineItem()
{
this.amount = new SimpleObjectProperty<>();
}
public BigDecimal getTotal()
{
return this.amount.get();
}
}
Ideally, changes to the properties will reflect in the total property...
Solution
There are a few changes to make to make this work:
- You need to define a "property accessor" method in your
LineItem
class, to access the actualObjectProperty<BigDecimal>
(not just theBigDecimal
it wraps). This allows the list to send notifications if the individual amounts change. - You need to create your
ObservableList
with an "extractor", so it can send update notifications to your binding, if the individual amount properties change - Fix the function in the binding to sum the
BigDecimal
instances, as described in this question
This looks like:
public class LineItem {
private final SimpleObjectProperty<BigDecimal> amount;
public LineItem()
{
this.amount = new SimpleObjectProperty<>();
}
public final BigDecimal getTotal()
{
return this.amount.get();
}
public ObjectProperty<BigDecimal> totalProperty() {
return amount ;
}
public final void setTotal(BigDecimal total) {
totalProperty().set(total);
}
}
then
ObservableList<LineItem> items = FXCollections.observableArrayList(
item -> new Observable[] {item.totalProperty()}
);
and
total.bind(Bindings.createObjectBinding(() -> items.stream()
.map(LineItem::getTotal)
.reduce(BigDecimal.ZERO, BigDecimal::add),
items));
Answered By - James_D
Answer Checked By - Katrina (JavaFixing Volunteer)