JavaFX TreeTableView Tutorial with Examples
1. JavaFX TreeTableView
JavaFX supplies you with class TreeTableView and it is used together with TreeItem, TreeTableColumn and TreeTableCell that helps you to display data in Tabular and in tree. Let's see the illustration below:
The same as TableView, you can create nested columns. In order to create a TreeTableView, you need:
- To add TreeItem to TreeTableView in order to form a tree structure.
- To define the columns of table.
- To define the way to display data on each cell via TreeTableColumn.setCellValueFactory method.
2. TreeTableView example
Creating a TreeTableView and adding more columns
TreeTableView<Employee> treeTableView = new TreeTableView<Employee>();
// Create column EmpNo (Data type of String).
TreeTableColumn<Employee, String> empNoCol //
= new TreeTableColumn<Employee, String>("Emp No");
.....
// Add columns to TreeTable.
treeTableView.getColumns().addAll(empNoCol, fullNameCol,
positionCol, genderCol, singleCol);
Creating TreeItem and adding to TreeTableView to form a tree structure:
// Data
Employee empBoss = new Employee("E00", "Abc@gmail.com", //
"Boss", "Boss", "Manager", "M", false);
Employee empSmith = new Employee("E01", "Smith@gmail.com", //
"Susan", "Smith", "Salesman", "F", true);
Employee empMcNeil = new Employee("E02", "McNeil@gmail.com", //
"Anne", "McNeil", "Cleck", "M", false);
// Root Item
TreeItem<Employee> itemRoot = new TreeItem<Employee>(empBoss);
TreeItem<Employee> itemSmith = new TreeItem<Employee>(empSmith);
TreeItem<Employee> itemMcNeil = new TreeItem<Employee>(empMcNeil);
itemRoot.getChildren().addAll(itemSmith, itemMcNeil);
// Set root Item for Tree
treeTableView.setRoot(itemRoot);
Defining the way to display data on each cell of tree.
// Defines how to fill data for each cell.
// Get value from property of Employee.
empNoCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("empNo"));
firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("firstName"));
lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("lastName"));
positionCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("position"));
genderCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("gender"));
singleCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, Boolean>("single"));
View full example:
TreeTableViewDemo.java
package org.o7planning.javafx.treetableview;
import org.o7planning.javafx.model.Employee;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class TreeTableViewDemo extends Application {
@Override
public void start(Stage stage) {
TreeTableView<Employee> treeTableView = new TreeTableView<Employee>();
// Create column EmpNo (Data type of String).
TreeTableColumn<Employee, String> empNoCol //
= new TreeTableColumn<Employee, String>("Emp No");
// Create column FullName (Data type of String).
TreeTableColumn<Employee, String> fullNameCol//
= new TreeTableColumn<Employee, String>("Full Name");
// Create 2 sub column for FullName.
TreeTableColumn<Employee, String> firstNameCol //
= new TreeTableColumn<Employee, String>("First Name");
TreeTableColumn<Employee, String> lastNameCol //
= new TreeTableColumn<Employee, String>("Last Name");
// Add sub columns to the FullName
fullNameCol.getColumns().addAll(firstNameCol, lastNameCol);
// Gender Column
TreeTableColumn<Employee, String> genderCol //
= new TreeTableColumn<Employee, String>("Gender");
// Position Column
TreeTableColumn<Employee, String> positionCol //
= new TreeTableColumn<Employee, String>("Position");
// Single? Column
TreeTableColumn<Employee, Boolean> singleCol//
= new TreeTableColumn<Employee, Boolean>("Single?");
// Defines how to fill data for each cell.
// Get value from property of Employee.
empNoCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("empNo"));
firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("firstName"));
lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("lastName"));
positionCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("position"));
genderCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("gender"));
singleCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, Boolean>("single"));
// Add columns to TreeTable.
treeTableView.getColumns().addAll(empNoCol, fullNameCol,positionCol, genderCol, singleCol);
// Data
Employee empBoss = new Employee("E00", "Abc@gmail.com", //
"Boss", "Boss", "Manager", "M", false);
Employee empSmith = new Employee("E01", "Smith@gmail.com", //
"Susan", "Smith", "Salesman", "F", true);
Employee empMcNeil = new Employee("E02", "McNeil@gmail.com", //
"Anne", "McNeil", "Cleck", "M", false);
// Root Item
TreeItem<Employee> itemRoot = new TreeItem<Employee>(empBoss);
TreeItem<Employee> itemSmith = new TreeItem<Employee>(empSmith);
TreeItem<Employee> itemMcNeil = new TreeItem<Employee>(empMcNeil);
itemRoot.getChildren().addAll(itemSmith, itemMcNeil);
treeTableView.setRoot(itemRoot);
//
StackPane root = new StackPane();
root.setPadding(new Insets(5));
root.getChildren().add(treeTableView);
stage.setTitle("TreeTableView (o7planning.org)");
Scene scene = new Scene(root, 450, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Employee.java
package org.o7planning.javafx.model;
public class Employee {
private String empNo;
private String firstName;
private String lastName;
private String email;
private String position;
private String gender;
private boolean single;
public Employee(String empNo, String email, //
String firstName, String lastName, String position, String gender, boolean single) {
this.empNo = empNo;
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
this.position = position;
this.gender = gender;
this.single = single;
}
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public boolean isSingle() {
return single;
}
public void setSingle(boolean single) {
this.single = single;
}
}
3. Edit data on TreeTableView
You can edit on TreeTableView directly, then data will be updated to Model. The image below illustrates a editable TreeTableView.
setCellFactory & setCellValueFactory
treeTableColumn.setCellValueFactory
- Is the method specifying how to display the data on cell of TreeTableView.
- Is the method specifying how to render a control while the user is editing data on the Cell..
onCellEditComit
Next, you need to define how new data will be updated to Model using treeTableColumn.setOnEditCommit method. After editing on the cell of table, the new data will be updated to Model.
With the cells show CheckBox in TableView:Note that the CheckBoxTreeTableCell renders the CheckBox 'live', meaning that the CheckBox is always interactive and can be directly toggled by the user. This means that it is not necessary that the cell enter its editing state (usually by the user double-clicking on the cell). A side-effect of this is that the usual editing callbacks (such as on edit commit) will not be called. If you want to be notified of changes, it is recommended to directly observe the boolean properties that are manipulated by the CheckBox.
View full example:
TreeTableViewEditDemo.java
package org.o7planning.javafx.treetableview;
import org.o7planning.javafx.model.Employee;
import org.o7planning.javafx.model.Gender;
import javafx.application.Application;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.CheckBoxTreeTableCell;
import javafx.scene.control.cell.ComboBoxTreeTableCell;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TreeTableViewEditDemo extends Application {
@Override
public void start(Stage stage) {
TreeTableView<Employee> treeTableView = new TreeTableView<Employee>();
treeTableView.setEditable(true);
// Create column EmpNo (Data type of String).
TreeTableColumn<Employee, String> empNoCol //
= new TreeTableColumn<Employee, String>("Emp No");
// Create column FullName (Data type of String).
TreeTableColumn<Employee, String> fullNameCol//
= new TreeTableColumn<Employee, String>("Full Name");
// Create 2 sub column for FullName.
TreeTableColumn<Employee, String> firstNameCol //
= new TreeTableColumn<Employee, String>("First Name");
TreeTableColumn<Employee, String> lastNameCol //
= new TreeTableColumn<Employee, String>("Last Name");
// Add sub columns to the FullName
fullNameCol.getColumns().addAll(firstNameCol, lastNameCol);
// Gender Column
TreeTableColumn<Employee, Gender> genderCol //
= new TreeTableColumn<Employee, Gender>("Gender");
genderCol.setMinWidth(90);
// Position Column
TreeTableColumn<Employee, String> positionCol //
= new TreeTableColumn<Employee, String>("Position");
// Single? Column
TreeTableColumn<Employee, Boolean> singleCol//
= new TreeTableColumn<Employee, Boolean>("Single?");
// Add columns to TreeTable.
treeTableView.getColumns().addAll(empNoCol, fullNameCol, positionCol, genderCol, singleCol);
// Data
Employee empBoss = new Employee("E00", "Abc@gmail.com", //
"Boss", "Boss", "Manager", "M", false);
Employee empSmith = new Employee("E01", "Smith@gmail.com", //
"Susan", "Smith", "Salesman", "F", true);
Employee empMcNeil = new Employee("E02", "McNeil@gmail.com", //
"Anne", "McNeil", "Cleck", "M", false);
// Root Item
TreeItem<Employee> itemRoot = new TreeItem<Employee>(empBoss);
TreeItem<Employee> itemSmith = new TreeItem<Employee>(empSmith);
TreeItem<Employee> itemMcNeil = new TreeItem<Employee>(empMcNeil);
itemRoot.getChildren().addAll(itemSmith, itemMcNeil);
treeTableView.setRoot(itemRoot);
// Defines how to fill data for each cell.
// Get value from property of Employee.
empNoCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("empNo"));
firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("firstName"));
lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("lastName"));
positionCol.setCellValueFactory(new TreeItemPropertyValueFactory<Employee, String>("position"));
// GENDER (COMBO BOX).
genderCol.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<Employee, Gender>, //
ObservableValue<Gender>>() {
@Override
public ObservableValue<Gender> call(TreeTableColumn.CellDataFeatures<Employee, Gender> param) {
TreeItem<Employee> treeItem = param.getValue();
Employee emp = treeItem.getValue();
// F,M
String genderCode = emp.getGender();
Gender gender = Gender.getByCode(genderCode);
return new SimpleObjectProperty<Gender>(gender);
}
});
ObservableList<Gender> genderList = FXCollections.observableArrayList(//
Gender.values());
genderCol.setCellFactory(ComboBoxTreeTableCell.forTreeTableColumn(genderList));
// After user edit on cell, update to Model.
genderCol.setOnEditCommit(new EventHandler<TreeTableColumn.CellEditEvent<Employee, Gender>>() {
@Override
public void handle(TreeTableColumn.CellEditEvent<Employee, Gender> event) {
TreeItem<Employee> item = event.getRowValue();
Employee emp = item.getValue();
Gender newGender = event.getNewValue();
emp.setGender(newGender.getCode());
System.out.println("Single column commit. new gender:" +newGender);
System.out.println("EMP:"+emp.isSingle());
}
});
// ==== SINGLE? (CHECH BOX) ===
singleCol.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<Employee, Boolean>, //
ObservableValue<Boolean>>() {
@Override
public ObservableValue<Boolean> call(TreeTableColumn.CellDataFeatures<Employee, Boolean> param) {
TreeItem<Employee> treeItem = param.getValue();
Employee emp = treeItem.getValue();
SimpleBooleanProperty booleanProp= new SimpleBooleanProperty(emp.isSingle());
// Note: singleCol.setOnEditCommit(): Not work for
// CheckBoxTreeTableCell.
// When "Single?" column change.
booleanProp.addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue,
Boolean newValue) {
emp.setSingle(newValue);
}
});
return booleanProp;
}
});
singleCol.setCellFactory(new Callback<TreeTableColumn<Employee,Boolean>,TreeTableCell<Employee,Boolean>>() {
@Override
public TreeTableCell<Employee,Boolean> call( TreeTableColumn<Employee,Boolean> p ) {
CheckBoxTreeTableCell<Employee,Boolean> cell = new CheckBoxTreeTableCell<Employee,Boolean>();
cell.setAlignment(Pos.CENTER);
return cell;
}
});
//
StackPane root = new StackPane();
root.setPadding(new Insets(5));
root.getChildren().add(treeTableView);
stage.setTitle("TreeTableView (o7planning.org)");
Scene scene = new Scene(root, 450, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Gender.java
package org.o7planning.javafx.model;
public enum Gender {
FEMALE("F", "Famale"), MALE("M", "Male");
private String code;
private String text;
private Gender(String code, String text) {
this.code = code;
this.text = text;
}
public String getCode() {
return code;
}
public String getText() {
return text;
}
public static Gender getByCode(String genderCode) {
for (Gender g : Gender.values()) {
if (g.code.equals(genderCode)) {
return g;
}
}
return null;
}
@Override
public String toString() {
return this.text;
}
}
JavaFX Tutorials
- Open a new Window in JavaFX
- JavaFX ChoiceDialog Tutorial with Examples
- JavaFX Alert Dialogs Tutorial with Examples
- JavaFX TextInputDialog Tutorial with Examples
- Install e(fx)clipse for Eclipse (JavaFX Tooling)
- Install JavaFX Scene Builder for Eclipse
- JavaFX Tutorial for Beginners - Hello JavaFX
- JavaFX FlowPane Layout Tutorial with Examples
- JavaFX TilePane Layout Tutorial with Examples
- JavaFX HBox, VBox Layout Tutorial with Examples
- JavaFX BorderPane Layout Tutorial with Examples
- JavaFX AnchorPane Layout Tutorial with Examples
- JavaFX TitledPane Tutorial with Examples
- JavaFX Accordion Tutorial with Examples
- JavaFX ListView Tutorial with Examples
- JavaFX Group Tutorial with Examples
- JavaFX ComboBox Tutorial with Examples
- JavaFX Transformations Tutorial with Examples
- JavaFX Effects Tutorial with Examples
- JavaFX GridPane Layout Tutorial with Examples
- JavaFX StackPane Layout Tutorial with Examples
- JavaFX ScrollPane Tutorial with Examples
- JavaFX WebView and WebEngine Tutorial with Examples
- JavaFX HTMLEditor Tutorial with Examples
- JavaFX TableView Tutorial with Examples
- JavaFX TreeView Tutorial with Examples
- JavaFX TreeTableView Tutorial with Examples
- JavaFX Menu Tutorial with Examples
- JavaFX ContextMenu Tutorial with Examples
- JavaFX Image and ImageView Tutorial with Examples
- JavaFX Label Tutorial with Examples
- JavaFX Hyperlink Tutorial with Examples
- JavaFX Button Tutorial with Examples
- JavaFX ToggleButton Tutorial with Examples
- JavaFX RadioButton Tutorial with Examples
- JavaFX MenuButton and SplitMenuButton Tutorial with Examples
- JavaFX TextField Tutorial with Examples
- JavaFX PasswordField Tutorial with Examples
- JavaFX TextArea Tutorial with Examples
- JavaFX Slider Tutorial with Examples
- JavaFX Spinner Tutorial with Examples
- JavaFX ProgressBar and ProgressIndicator Tutorial with Examples
- JavaFX ChoiceBox Tutorial with Examples
- JavaFX Tooltip Tutorial with Examples
- JavaFX DatePicker Tutorial with Examples
- JavaFX ColorPicker Tutorial with Examples
- JavaFX FileChooser and DirectoryChooser Tutorial with Examples
- JavaFX PieChart Tutorial with Examples
- JavaFX AreaChart and StackedAreaChart Tutorial with Examples
- JavaFX BarChart and StackedBarChart Tutorial with Examples
- JavaFX Line Tutorial with Examples
- JavaFX Rectangle and Ellipse Tutorial with Examples
Show More