0

I try to find a solution for my problem, but I'm at a dead end of my attempt and my small JavaFX skills.

Long story short, I want to activate a Button when two TextFields contains valid values and a ListView contains data.

To do this, I used the initialize() method and do the following:

// fill the first TextField with String values from above textfields
textFieldPointCloudName.textProperty().bind(pointCloudNameBinding);

and

// fill the second TextField from a DirectoryChooser or the clipboard and check its values
var isTargetPathValid = Bindings.createBooleanBinding(
                () -> {
                    var path = pointCloudPath.getText();
                    if (path.isEmpty()) {
                        return false;
                    } else {
                        return FileUtils.isDirectory(path);
                    }
                }, pointCloudPath.textProperty());

The bindings and checks of the two TextFields are done and they are working. I can activate the button on this two bindings with

// checks the TextFields and enable the execute/run button if not empty
btnRun.disableProperty().bind(areTextFieldsEmpty);

I used this code also in another program.

Now I tried to add the check for the ListView, which is this one:

@FXML
private ListView<File> listView;

The ListView is populated with data in a separate method, when the user hit OK in a FileChooser dialog.

var selectedFiles = fileChooser.showOpenMultipleDialog(window);
var files = FXCollections.observableArrayList(selectedFiles);

listView.setItems(files);
    // remove double-clicked items from the list
    listView.setOnMouseClicked(mouseEvent -> {
        if (mouseEvent.getClickCount() == 2) {
            var selectedIndex = listView.getSelectionModel().getSelectedIndex();
            listView.getItems().remove(selectedIndex);
        }
    });

Every attempt I tried failed.

I guess, that in the initialize() method, I missed something or do not understand how to bind it, or how to add a Listener or anything else.

When I bind the listView or the listView.itemsProperty() it is not updated when adding File objects or Strings to the list.

Any hint, how to do it, or what I'm missing?

3
  • Setup a boolean variable with initial value to false. Add onchange listeners on all fiellds you want inspect. If all fields matches your criteria set the boolean variable to true. If it is true enable your button. Commented Apr 13 at 12:39
  • 1
    I imagine you could use btnRun.disableProperty().bind(textFieldPointCloudName.textProperty().isEmpty().or(pointCloudText.getProperty().isEmpty()).or(listView.itemsProperty().flatMap(list -> Bindings.isEmpty(list)))); … but would this logic be obvious to a user? When a complex set of conditions determine the availability of an action, it’s often better to leave the button enabled, and instead display an error informing the user of what they must do to enable the action. Commented Apr 13 at 14:42
  • Great hint. Appreciate. With a couple of correction, combination and search engine work I found a solution. ListProperty<File> listProperty = new SimpleListProperty<>(); listProperty.bind(listView.itemsProperty()); btnRun.disableProperty().bind(areTextFieldsEmpty.or(listProperty.emptyProperty())); Commented Apr 13 at 18:10

1 Answer 1

1

With the hint of the comments I found a working solution! Thank you for this.

Maybe this is not the best, but a good working solution.

ListProperty<File> listProperty = new SimpleListProperty<>();
listProperty.bind(listView.itemsProperty());

btnRun.disableProperty().bind(areTextFieldsEmpty.or(listProperty.emptyProperty()));

Short enough to understand and working.

Sign up to request clarification or add additional context in comments.

4 Comments

The listProperty seems redundant. Assuming JavaFX 19 or later, I think you could just do var listEmpty = listView.itemsProperty().map(ObservableList::isEmpty); and then btnRun.disableProperty().bind(areTextFieldsEmpty.or(listEmpty));, or similar.
@James_D Wrong argument type. I can't cast it to ObservableBooleanValue.
Ah yes, that makes sense.
If you don't ever swap out the ObservableList in the list view's items property, then another approach is to use Bindings#isEmpty(ObservableList). That method returns a BooleanBinding which is an ObservableBooleanValue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.