Suppose I have an ObservableList
and a Button
in the same controller class:
private ObservableList<NameItem> _selectedList = _database.getONameList();
@FXML
private Button nextButton;
How do I make it so that the Button
is only enabled while the ObservableList
is not empty? Is there a binding property I can use to set this?
This can be done fairly easily with just a couple of simple Bindings, actually.
First, you want to create an IntegerBinding
that is bound to the size of your ObservableList
:
IntegerBinding listSize = Bindings.size(_selectedList);
Then create a new BooleanBinding
that is bound to whether or not the listSize
binding is greater than 0:
BooleanBinding listPopulated = listSize.greaterThan(0);
Now, all you need to do is bind the button's disableProperty
to the opposite of the listPopulated
property using the not()
method (since listPopulated
will be true
if items are in the list, you want to actually pass false
to the button's disableProperty
):
button.disableProperty().bind(listPopulated.not());
Here is a quick MCVE to demonstrate:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
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.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Simple interface
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
// Create an empty ObservableList
ObservableList<String> list = FXCollections.observableArrayList();
// Create a binding to extract the list's size to a property
IntegerBinding listSizeProperty = Bindings.size(list);
// Create a boolean binding that will return true only if the list has 1 or more elements
BooleanBinding listPopulatedProperty = listSizeProperty.greaterThan(0);
// Create the button we want to enable/disable
Button button = new Button("Submit");
// Bind the button's disableProperty to the opposite of the listPopulateProperty
// If listPopulateProperty is false, the button will be disabled, and vice versa
button.disableProperty().bind(listPopulatedProperty.not());
// Create another button to add an item to the list, just to demonstrate the concept
Button btnAddItem = new Button("Add Item");
btnAddItem.setOnAction(event -> {
list.add("New Item");
System.out.println(list.size());
});
// Add the buttons to the layout
root.getChildren().addAll(btnAddItem, button);
// Show the Stage
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
In the above example, the "Submit" button is disabled until you add an item to the ObservableList
using the "Add Item" button.
EDIT: As Lukas excellently points out in the comments below, these Bindings can also all be chained together to simplify things (either method is equally valid; it just depends on which you find more readable, really):
button.disableProperty().bind(Bindings.size(list).greaterThan(0).not())
Another Method
Another way to do this is with a ListChangeListener
that enables or disables the button any time the list changes:
list.addListener((ListChangeListener<String>) c -> {
// If the size of the list is less than 1, disable the button; otherwise enable it
button.setDisable(c.getList().size() < 1);
});
This will essentially do exactly the same thing as the first method, but you'll need to set the initial state of the button yourself before the listener can keep it updated for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With