12 GUI + JavaFX Ⅱ

Graphical User Interfaces with JavaFX Ⅱ

Objective

  • Bind UI components to model objects to allow the user to add, update, and delete objects listed in a TableView.
  • Use common UI components including Label, Button, ComboBox, DatePicker, RadioButton, ToggleGroup, TableView, TableColumn, ToolBar, and Separator.
  • Use PropertyValueFactory and ObservableList to bind data to components and Dialog to create modal dialogs.

Summary

  1. Data binding allows synchronization between the user interface components and the underlying data model.
  2. Data binding ensures that changes in the data model are automatically reflected in the user interface.
  3. Reading and writing files are combined with a graphical user interface for a user-friendly interactive experience.

Exercise 1*

Country Explorer

  1. Create a Country class based on the following diagram:
Country-name: String-alpha3: String-continent: String-region: String+get*():type+set*(type): void+toString(): String
  1. Create a CountryRepository model class to hold the list of countries and implement a method to load all the countries from data/countries.csv (countries.csv).
CountryRepository-countries: List<Country>+getCountries(): List<Country>-loadCountries(): void+getContinents(): List<String>+getRegions(String): List<String>+getCountriesRegion(String): List<Country>

The CSV file can be read line-by-line and each line split into its fields:

CountryRepository.java
String line = scanner.nextLine();
String[] tokens = line.split(",");
countries.add(new Country(tokens[0], tokens[1], tokens[2], tokens[3]));
  1. Create a CountryView view to display all the countries along with their details using a TableView.

    Countries

    The Name column, for example, can be created and bound using:

    CountryView.java
    TableView<Country> countryTable = new TableView<>();
    TableColumn<Country, String> nameCol = new TableColumn<>("Name");
    nameCol.setCellValueFactory(new PropertyValueFactory<Country, String>("name"));
    countryTable.getColumns().add(nameCol);

    The list of countries can be bound to the table view using:

    countryTable.setItems(FXCollections.observableArrayList(CountryRepository.getCountries()));
  2. Update the view to be able to filter countries based on the currently selected continent and region. You need to add the required components and implement the corresponding event handlers. Use a Toolbar to host the labels and dropdown lists.

    Countries

    The list of continents can be bound to the dropdown list using:

    continentComboBox.setItems(FXCollections.observableArrayList(CountryRepository.getContinents()));

Exercise 2

Trip Register

  1. Create a Trip class based on the following diagram:
Trip-accounts: String-type: String-fromDate: LocalDate-toDate: LocalDate-rating: String+get*():type+set*(type): void+toString(): String
  1. Create a TripRepository model class to hold the list of trips and implement methods to load/save all the trips from/to data/trips.csv (trips.csv).
TripRepository-trips: List<Trip>+getTrips(): List<Trip>-loadTrips(): void+saveTrips(): void+getCountries(): List<String>+getTypes(): List<String>+getRatings(): List<String>
  1. Create a TripView view to display all the trips along with their details using a TableView.

    Trips

  2. Add buttons to add, update, and delete a trip. Add a button to save all the trips as well.

  3. Create a TripEditorView view to display and edit the details of a trip. This can be used to add a new trip or update a selected trip from the table.

    Trip Editor

    You can check whether an item is selected in the table or not using:

    TripView.java
    updateButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent event) {
        int index = tripTable.getSelectionModel().getSelectedIndex();
        if (index != -1) {
          ...
        }
      }
    }
  4. Create a TripEditorDialog modal dialog and use it to add new trips or update existing ones. A modal dialog can be created using:

    TripEditorDialog.java
    Dialog<ButtonType> dialog = new Dialog<>();
    TripEditorView view = new TripEditorView(trip);
    dialog.getDialogPane().setContent(view.getRoot());
    dialog.getDialogPane().getButtonTypes().addAll(ButtonType.CANCEL, ButtonType.OK);
    Optional<ButtonType> result = dialog.showAndWait();
    ButtonType button = result.orElse(ButtonType.CANCEL);
     
    if (button == ButtonType.OK) {
      ...
    }