Skip to content

Latest commit

 

History

History
87 lines (64 loc) · 3.92 KB

2020-12-05-EN-navigation-using-a-listview-in-javafx.md

File metadata and controls

87 lines (64 loc) · 3.92 KB
layout title slug date categories lang ref excerpt_separator
post
Navigation using a ListView in JavaFX
navigation-using-a-listview-in-javafx
2020-12-05 21:43:00 -0400
100-days-javafx
en
navigation-using-a-listview-in-javafx
<!--more-->

The [Schema Editor app]({% post_url 2020-11-14-EN-new-project-json-schema-app %}) I've been working on has two main panes in its UI: the menu on the left and the editor and the center.

In the previous posts we were able to [create a reactive menu]({% post_url 2020-12-03-EN-observable-collection-and-listview-in-javafx %}) and [make the name of the schema editable]({% post_url 2020-12-05-EN-editable-listview-cells-in-javafx %}).

The Application after it started

React when an Schema is selected in the ListView

We want the editor view to reflect the correct schema when selecting the schema from the ListView.

This not something you can do in FXML. However you can get a property that tracks the currently selected item: listView.getSelectionModel().selectedItemProperty()

public class AppController {
    @FXML private ListView<Schema> schemaListView;
    @FXML private TextArea schemaEditor;

    private final ObjectProperty<Schema> selectedSchemaProperty 
        = new SimpleObjectProperty<>();

    @FXML
    public void initialize() throws IOException {
        ObservableList<Schema> schemas = FXCollections.observableArrayList();
        schemaListView.setEditable(true);
        schemaListView.setCellFactory(param -> new SchemaListCell());
        schemaListView.setItems(schemas);

        selectedSchemaProperty.bind(schemaListView.getSelectionModel().selectedItemProperty());
        selectedSchemaProperty.addListener((observable, oldValue, newValue) -> {
            schemaEditor.setText(newValue.getRaw());
        });

        // Load data
        InitialDataLoader dataLoader = new InitialDataLoader();
        schemas.addAll(dataLoader.load());
    }
}

Don't forget to add fx:id="schemaEditor" to the TextArea in the .fxml file.

Textarea updates based on the selected item in the ListView

Textarea updates based on the selected item in the ListView.

Using EasyBind

I worked in the past with RxJava which also have a type called Observable (its sematic varies from the JavaFX Observable though). One of the thing that I enjoy was possibility to use function such as .map() to transform an observable.

While the Bindings util class offers some tools to do transformation of observables, I am not found of its ergonomics. I prefer to use the EasyBind library instead:

// When the selected schema changes
selectedSchemaProperty.bind(schemaListView.getSelectionModel().selectedItemProperty());
schemaEditor.textProperty().bind(
    EasyBind.monadic(selectedSchemaProperty)
        .selectProperty(Schema::rawProperty)
);

I could skip using the selectedSchemaProperty variable altogether:

// When the selected schema changes
schemaEditor.textProperty().bind(
    EasyBind.monadic(schemaListView.selectionModelProperty())
        .flatMap(SelectionModel::selectedItemProperty)
        .selectProperty(Schema::rawProperty)
);

Don't forget to add the esybind dependency to your pom.xml and module-info.java files.

I'm a big fan of monads as they allow to make my code linear, hence easier to read.