Руководство JavaFX TreeTableView
1. JavaFX TreeTableView
JavaFX предоставляет вам класс TreeTableView, который может быть использовать с TreeItem, TreeTableColumn и TreeTableCell помогающий вам отобразить данные в виде таблицы (Tabular) и одновременно в виде дерева. Можете посмотреть изображение ниже:
Похоже на TableView вы можене создать сплетенные столбцы. Чтобы создать TreeTableView вам нужно:
- Добавить TreeItem в TreeTableView чтобы получить структуру дерева.
- Дать определения столбцам в таблице.
- Дать определение способу отображения данных на каждой ячейке через метод TreeTableColumn.setCellValueFactory.
2. Пример с TreeTableView
Создать объект TreeTableView и добавить столбцы (TreeTableColumn).
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);
Создать TreeItem и добавить в TreeTableView чтобы получить структуру дерева:
// 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);
Определить способ отображения данных на каждой ячейке дерева.
// 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"));
Смотреть полный пример:
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. Изменить данные на TreeTableView
Вы можете изменить прямо на TreeTableView, данные будут обновлены в Model. Изображение ниже иллюстрирует редактируемый TreeTableView.
setCellFactory & setCellValueFactory
treeTableColumn.setCellValueFactory
- Это метод определения способа получения данных, и эти данные будут отображены на ячейке TreeTableView.
- Это метод определения способа рендеринга (render) управления (Controls) когда пользователь меняет данные в ячейке.
onCellEditComit
Далее, вам нужно определить как новые данные будут обновлены в Model, используя метод treeTableColumn.setOnEditCommit. После того как пользователь изменил ячейку на TreeTableView новые данные будут обновлены в Model.
С ячейками отображающими CheckBox на TreeTableView:Заметьте, что CheckBoxTreeTableCell отрисовка (render) CheckBox 'живой', означает что CheckBox всегда интерактивный и может быть переключен пользователем. Это означает что необязательно менять состояние редактирования (обычно чтобы изменить состояние редактирования, пользователь кликает на ячейку два раза). Побочным эффекторм является то, что обычные callbacks редактирования (например onCommitEdit) не будут вызваны. Если вы хотите быть оповещены про изменения, вам следует работать с наблюдателем (Observe) свойства boolean манипулированные CheckBox-ом.
Смотреть полный пример:
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
- Откройте новое окно (window) в JavaFX
- Руководство JavaFX ChoiceDialog
- Руководство JavaFX Alert Dialog
- Руководство JavaFX TextInputDialog
- Установите e(fx)clipse для Eclipse (JavaFX Tooling)
- Установите JavaFX Scene Builder для Eclipse
- Руководство JavaFX для начинающих - Hello JavaFX
- Руководство JavaFX FlowPane Layout
- Руководство JavaFX TilePane Layout
- Руководство JavaFX HBox, VBox Layout
- Руководство JavaFX BorderPane Layout
- Руководство JavaFX AnchorPane Layout
- Руководство JavaFX TitledPane
- Руководство JavaFX Accordion
- Руководство JavaFX ListView
- Руководство JavaFX Group
- Руководство JavaFX ComboBox
- Руководство JavaFX Transformations
- Эффекты (effects) в JavaFX
- Руководство JavaFX GridPane Layout
- Руководство JavaFX StackPane Layout
- Руководство JavaFX ScrollPane
- Руководство JavaFX WebView и WebEngine
- Руководство JavaFX HTMLEditor
- Руководство JavaFX TableView
- Руководство JavaFX TreeView
- Руководство JavaFX TreeTableView
- Руководство JavaFX Menu
- Руководство JavaFX ContextMenu
- Руководство JavaFX Image и ImageView
- Руководство JavaFX Label
- Руководство JavaFX Hyperlink
- Руководство JavaFX Button
- Руководство JavaFX ToggleButton
- Руководство JavaFX RadioButton
- Руководство JavaFX MenuButton и SplitMenuButton
- Руководство JavaFX TextField
- Руководство JavaFX PasswordField
- Руководство JavaFX TextArea
- Руководство JavaFX Slider
- Руководство JavaFX Spinner
- Руководство JavaFX ProgressBar и ProgressIndicator
- Руководство JavaFX ChoiceBox
- Руководство JavaFX Tooltip
- Руководство JavaFX DatePicker
- Руководство JavaFX ColorPicker
- Руководство JavaFX FileChooser и DirectoryChooser
- Руководство JavaFX PieChart
- Руководство JavaFX AreaChart и StackedAreaChart
- Руководство JavaFX BarChart и StackedBarChart
- Руководство JavaFX Line
- Руководство JavaFX Rectangle и Ellipse
Show More