Reputation: 10253
I have a Label
that needs to display the number of elements in an ObservableList
. I have the IntegerBinding
setup, but I also need to adjust the wording of the Label
based on how many elements are in the list.
For the MCVE below, if there is only one element in the list, it should display "The list contains 1 item." But "item" needs to be plural if the list is empty or contains multiple items: "The list contains 3 items."
I have tried to do so using both a ternary operator and a BooleanBinding
, but neither has any effect as the ternary expression only seems to be evaluated once. Clicking the "Add" button does not change the "items" portion of the Label
.
THE CODE
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.IntegerBinding;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
ObservableList<String> items = FXCollections.observableArrayList();
private IntegerBinding listSize = Bindings.size(items);
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
Label label = new Label();
// Bind the label to display a size-aware notification
label.textProperty().bind(
Bindings.concat("The list contains ", listSize,
((items.size() != 1) ? " items!" : " item!"))
);
// Button to add items
Button button = new Button("Add");
button.setOnAction(event -> items.add("new item"));
root.getChildren().addAll(label, button);
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sample");
primaryStage.show();
}
}
Upvotes: 4
Views: 1215
Reputation: 8363
This is the shorter equivalent:
label.textProperty().bind(Bindings.createStringBinding(
() -> "The list contains " + listSize.get() + ((itemSize.get() != 1) ? " items!" : " item!",
listSize
));
Or another alternative:
label.textProperty.bind(Bindings
.when(listSize.isEqualTo(1))
.then("The list contains 1 item!")
.otherwise(
Bindings.concat("The list contains " + listSize + " items!")
)
);
Upvotes: 4
Reputation: 2917
Here is a quick solution using a custom StringBinding()
// Bind the label to display a size-aware notification
label.textProperty().bind(new StringBinding() {
{ bind(listSize); }
@Override
protected String computeValue() {
return "The list contains " + listSize.get() + ((items.size() != 1) ? " items!" : " item!");
}
});
In the code above you will listen to the listSize for changes and then you will create the new String inside the computeValue().
Upvotes: 3