JavaFX Tutorial - JavaFX TreeTableView








JavaFX TreeTableView presents an hierarchy of data in table columns.

The TreeTableView component combines the TreeView and TableView controls.

import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableColumn.CellDataFeatures;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
// w  w w  . j a  v  a 2  s.  co m
public class Main extends Application {
  public static void main(String[] args) {
    Application.launch(args);
  }
  @Override
  public void start(Stage stage) {
    final Scene scene = new Scene(new Group(), 200, 400);
    Group sceneRoot = (Group) scene.getRoot();

    TreeItem<String> childNode1 = new TreeItem<>("Node 1");
    TreeItem<String> childNode2 = new TreeItem<>("Node 2");
    TreeItem<String> childNode3 = new TreeItem<>("Node 3");

    TreeItem<String> root = new TreeItem<>("Root");
    root.setExpanded(true);

    root.getChildren().setAll(childNode1, childNode2, childNode3);

    TreeTableColumn<String, String> column = new TreeTableColumn<>("Column");
    column.setPrefWidth(150);

    column.setCellValueFactory((CellDataFeatures<String, String> p) -> new ReadOnlyStringWrapper(
            p.getValue().getValue()));

    TreeTableView<String> treeTableView = new TreeTableView<>(root);
    treeTableView.getColumns().add(column);
    sceneRoot.getChildren().add(treeTableView);
    stage.setScene(scene);
    stage.show();
  }
}

The code above generates the following result.

null




Adding Several Columns

/*/*  w w w.j  ava2s  . c o  m*/
 * Copyright (c) 2008, 2014, Oracle and/or its affiliates.
 * All rights reserved. Use is subject to license terms.
 *
 * This file is available and licensed under the following license:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the distribution.
 *  - Neither the name of Oracle nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
import java.util.Arrays;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;

public class Main extends Application {

  List<Employee> employees = Arrays.<Employee> asList(new Employee(
      "Ethan Williams", "ethan.williams@example.com"), new Employee(
      "Emma Jones", "emma.jones@example.com"), new Employee("Michael Brown",
      "michael.brown@example.com"), new Employee("Anna Black",
      "anna.black@example.com"), new Employee("Rodger York",
      "roger.york@example.com"), new Employee("Susan Collins",
      "susan.collins@example.com"));

  final TreeItem<Employee> root = new TreeItem<>(new Employee(
      "Sales Department", ""));

  public static void main(String[] args) {
    Application.launch(Main.class, args);
  }

  @Override
  public void start(Stage stage) {
    root.setExpanded(true);
    employees.stream().forEach((employee) -> {
      root.getChildren().add(new TreeItem<>(employee));
    });
    Scene scene = new Scene(new Group(), 400, 400);
    Group sceneRoot = (Group) scene.getRoot();

    TreeTableColumn<Employee, String> empColumn = new TreeTableColumn<>(
        "Employee");
    empColumn.setPrefWidth(150);
    empColumn
        .setCellValueFactory((
            TreeTableColumn.CellDataFeatures<Employee, String> param) -> new ReadOnlyStringWrapper(
            param.getValue().getValue().getName()));

    TreeTableColumn<Employee, String> emailColumn = new TreeTableColumn<>(
        "Email");
    emailColumn.setPrefWidth(190);
    emailColumn
        .setCellValueFactory((
            TreeTableColumn.CellDataFeatures<Employee, String> param) -> new ReadOnlyStringWrapper(
            param.getValue().getValue().getEmail()));

    TreeTableView<Employee> treeTableView = new TreeTableView<>(root);
    treeTableView.getColumns().setAll(empColumn, emailColumn);
    sceneRoot.getChildren().add(treeTableView);
    stage.setScene(scene);
    stage.show();
  }

  public class Employee {

    private SimpleStringProperty name;
    private SimpleStringProperty email;

    public SimpleStringProperty nameProperty() {
      if (name == null) {
        name = new SimpleStringProperty(this, "name");
      }
      return name;
    }

    public SimpleStringProperty emailProperty() {
      if (email == null) {
        email = new SimpleStringProperty(this, "email");
      }
      return email;
    }

    private Employee(String name, String email) {
      this.name = new SimpleStringProperty(name);
      this.email = new SimpleStringProperty(email);
    }

    public String getName() {
      return name.get();
    }

    public void setName(String fName) {
      name.set(fName);
    }

    public String getEmail() {
      return email.get();
    }

    public void setEmail(String fName) {
      email.set(fName);
    }
  }
}

The code above generates the following result.

null




Altering Visual Appearance

treeTableView.setTableMenuButtonVisible(true) enables the table menu button, so that users can toggle the visibility of the table columns. The method adds the "+" button to the table header.

/*/*w ww. j a v a  2 s  .  c  o m*/
 * Copyright (c) 2008, 2014, Oracle and/or its affiliates.
 * All rights reserved. Use is subject to license terms.
 *
 * This file is available and licensed under the following license:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the distribution.
 *  - Neither the name of Oracle nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
import java.util.Arrays;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;

public class Main extends Application {

  List<Employee> employees = Arrays.<Employee> asList(new Employee(
      "Ethan Williams", "ethan.williams@example.com"), new Employee(
      "Emma Jones", "emma.jones@example.com"), new Employee("Michael Brown",
      "michael.brown@example.com"), new Employee("Anna Black",
      "anna.black@example.com"), new Employee("Rodger York",
      "roger.york@example.com"), new Employee("Susan Collins",
      "susan.collins@example.com"));

  final TreeItem<Employee> root = new TreeItem<>(new Employee(
      "Sales Department", ""));

  public static void main(String[] args) {
    Application.launch(Main.class, args);
  }

  @Override
  public void start(Stage stage) {
    root.setExpanded(true);
    employees.stream().forEach((employee) -> {
      root.getChildren().add(new TreeItem<>(employee));
    });
    Scene scene = new Scene(new Group(), 400, 400);
    Group sceneRoot = (Group) scene.getRoot();

    TreeTableColumn<Employee, String> empColumn = new TreeTableColumn<>(
        "Employee");
    empColumn.setPrefWidth(150);
    empColumn
        .setCellValueFactory((
            TreeTableColumn.CellDataFeatures<Employee, String> param) -> new ReadOnlyStringWrapper(
            param.getValue().getValue().getName()));

    TreeTableColumn<Employee, String> emailColumn = new TreeTableColumn<>(
        "Email");
    emailColumn.setPrefWidth(190);
    emailColumn
        .setCellValueFactory((
            TreeTableColumn.CellDataFeatures<Employee, String> param) -> new ReadOnlyStringWrapper(
            param.getValue().getValue().getEmail()));

    TreeTableView<Employee> treeTableView = new TreeTableView<>(root);
    treeTableView.getColumns().setAll(empColumn, emailColumn);
    
    treeTableView.setTableMenuButtonVisible(true);
    
    
    sceneRoot.getChildren().add(treeTableView);
    stage.setScene(scene);
    stage.show();
  }

  public class Employee {

    private SimpleStringProperty name;
    private SimpleStringProperty email;

    public SimpleStringProperty nameProperty() {
      if (name == null) {
        name = new SimpleStringProperty(this, "name");
      }
      return name;
    }

    public SimpleStringProperty emailProperty() {
      if (email == null) {
        email = new SimpleStringProperty(this, "email");
      }
      return email;
    }

    private Employee(String name, String email) {
      this.name = new SimpleStringProperty(name);
      this.email = new SimpleStringProperty(email);
    }

    public String getName() {
      return name.get();
    }

    public void setName(String fName) {
      name.set(fName);
    }

    public String getEmail() {
      return email.get();
    }

    public void setEmail(String fName) {
      email.set(fName);
    }
  }
}

We can show or hide the root tree item by using the setShowRoot method of the TreeTableView class.

treeTableView.setShowRoot(false);

The code above generates the following result.

null

Sort

We can sort data by clicking the column headers.

To set the descending mode of sorting for a column

aColumn.setSortType(TreeTableColumn.SortType.DESCENDING);

To set the ascending mode of sorting for a column

aColumn.setSortType(TreeTableColumn.SortType.ASCENDING);

To apply the sorting mode to all tree items

treeTableView.setSortMode(TreeSortMode.ALL_DESCENDANTS);

To apply the sorting mode only to the first-level nodes

treeTableView.setSortMode(TreeSortMode.ONLY_FIRST_LEVEL);

Managing Selection Mode

The default selection model for the TreeTableView class is SelectionMode.SINGLE.

To enable multiple selection of the tree items and cells, use a combination of the setSelectionModel and setCellSelectionEnabled methods.

To enable multiple selection for the Cells

treeTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
treeeTableView.getSelectionModel().setCellSelectionEnabled(true);