I got the following data model:
public class Player {
// enum to integer (count)
@Getter
private MapProperty<ResourceType, Integer> resourceCards = new SimpleMapProperty<>();
public void addResource(final ResourceType resourceType, final int amount) {
this.resourceCards.get().put(resourceType, this.resourceCards.get().get(resourceType) + amount);
}
}
public class Game {
@Getter
@Setter
private ObjectProperty<Player> currentPlayer = new SimpleObjectProperty<>();
}
Binding the map to a text property is quite easy:
final Label label = new Label();
label.textProperty().bind(EasyBind.select(game.getCurrentPlayer()).selectObject(player -> player.getResourceCards().asString()));
I would like to display the total amount of resource cards in the label.
Example:
Map: {Water=0, Gold=2, Lumber=5}
Label: 7
Map: {Water=0, Gold=0, Lumber=0}
Label: 0
How can I achieve this with JavaFX Bindings or/and EasyBind?
A MapProperty<S, T>
can be used as ObservableMap<S, T>
and gets notified of changes of the wrapped map. This means you can use Bindings.createStringBinding
on the map:
label.textProperty().bind(EasyBind.select(game.getCurrentPlayer())
.selectObject(player -> Bindings.createStringBinding(() -> Integer.toString(player.getResourceCards().values().stream().mapToInt(Integer::intValue).sum()),
player.getResourceCards())
.orElse("0")));
Note: Convention for the method name of the method returning the property object itself is using <propertyName>Property
. In case of your Game
's currentPlayer
property this would be currentPlayerProperty()
instead of getCurrentPlayer()
and resourceCardsProperty()
instead of getResourceCards()
. I used the method names including get
in the above code.
Furthermore using a MapProperty
is unnecessary unless you're planing to replace the whole map instead of simply modifying the Map
's contents. You could simply use a readonly property of type ObservableMap
in this case.