Issue
This works:
getTableView().itemsProperty().addListener((observableValue, oldVal, newVal) -> button.setDisable(newVal == null || newVal.isEmpty()));
When the tableview items are null or empty, the button is disabled.
I was wondering if there is a "binding" solution and how it would be implemented.
button.disableProperty().bind(Bindings.or(Bindings.isNull(getTableView().itemsProperty()), Bindings.isEmpty(getTableView().getItems())));
The above does not work because itemsProperty
is never null
and getItems()
may be null causing the Bindings.isEmpty()
to fail.
Solution
The ItemsProperty
of the TableView
is a simple ObservableProperty which does not provide any specialized functionality for tracking the items in an ObservableList.
You will want to create a ListProperty instead, which in turn provides the emptyProperty
that you can use for your purposes:
ListProperty<String> listProperty = new SimpleListProperty<>();;
Now bind that property to observe the ItemsProperty
of the TableView
:
listProperty.bind(tableView.itemsProperty());
The last step is just binding the disableProperty
of your Button
:
button.disableProperty().bind(listProperty.emptyProperty());
Below is a complete example using a ListView
instead of a TableView
. The functionality is identical but for the purposes of this example, a ListView
is just quicker to implement.
import javafx.application.Application;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ButtonBindingToList extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// **********************************************************************************************
// Create a basic layout
// **********************************************************************************************
VBox root = new VBox(5);
root.setAlignment(Pos.TOP_CENTER);
root.setPadding(new Insets(10));
// **********************************************************************************************
// Creat the ListView
// **********************************************************************************************
ListView<String> listView = new ListView<>();
// **********************************************************************************************
// Create a Button to add items to the list (will always be enabled).
// **********************************************************************************************
Button btnAdd = new Button("Add item");
btnAdd.setOnAction(event -> listView.getItems().add("Added item #" + listView.getItems().size()));
// **********************************************************************************************
// Create button to remove the last item in the ListView
// **********************************************************************************************
Button btnRemove = new Button("Remove last item");
btnRemove.setOnAction(event -> listView.getItems().remove(listView.getItems().size() - 1));
// **********************************************************************************************
// In order to bind to the emptiness of the ListView, we need to create a ListProperty that
// is bound to the ListView's itemsProperty
// **********************************************************************************************
ListProperty<String> listProperty = new SimpleListProperty<>();
listProperty.bind(listView.itemsProperty());
// **********************************************************************************************
// Now bind the "Remove" button's disable property to the listProperty. This will disable
// the button as long as the ListView is empty
// **********************************************************************************************
btnRemove.disableProperty().bind(listProperty.emptyProperty());
root.getChildren().addAll(listView, btnAdd, btnRemove);
// **********************************************************************************************
// Set the Scene for the stage
// **********************************************************************************************
primaryStage.setScene(new Scene(root));
// **********************************************************************************************
// Configure the Stage
// **********************************************************************************************
primaryStage.setTitle("Test Application");
primaryStage.show();
}
}
Answered By - Zephyr
Answer Checked By - Mary Flores (JavaFixing Volunteer)