JavaFX 树是 JavaFX 中的一种用于显示层次结构数据的 UI 组件。它可以用来显示文件夹和文件的层次结构,也可以用来显示 XML 文档的节点关系,或者用来显示其它有层次关系的数据。
JavaFX 树是一个可视化 UI 组件,它使用树形图表来表达层次性数据。树形图表中的节点可以有子节点,而子节点又可以有子节点,这样就形成了一个层次性的数据集合。
JavaFX 树有两个重要的特性:单选和多选。单选意味着在树中只能选中一个节点;而多选则意味着在树中可以选中多个节点。此外,JavaFX 树还允许开发者使用键盘快捷键来对树进行导航、扩展/收起子节点、选中/取消选中、剪切/复制/黏贴、重命名、删除、新增子节点、上下左右方向键进行导航。
TreeView<String> tree = new TreeView<>(); // 创建 TreeView 对象 TreeItem<String> root = new TreeItem<>("Root"); // 创建根 TreeItem 对象 root.setExpanded(true); // 让根 TreeItem 默认是扩展的 tree.setRoot(root); // 设定 TreeView 的根 TreeItem tree.setShowRoot(false); // 让 TreeView 默认不显式显出根 TreeItem
TreeView UI控件为我们提供了一种渲染树结构的方法。 树具有包含所有分层值的根节点。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
TreeItem<String> rootItem = new TreeItem<>("Root");
rootItem.setExpanded(true);
TreeItem<String> item = new TreeItem<>("A");
rootItem.getChildren().add(item);
item = new TreeItem<>("B");
rootItem.getChildren().add(item);
TreeView<String> tree = new TreeView<>(rootItem);
StackPane root = new StackPane();
root.getChildren().add(tree);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
上面的代码生成以下结果。
当创建树视图时,我们通常从构建根的TreeItem对象开始。 然后我们将根添加到树视图,并创建其他树项目对象并将它们添加到根。
我们可以通过setGraphic方法或使用它的构造函数来创建一个图形图标到树项目。 图标的建议大小为16x16。
对根项目调用的setExpanded方法定义树视图项目的初始外观。
以下代码从本地文件系统创建动态树。
import java.io.File;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
private TreeItem<File> createNode(final File f) {
return new TreeItem<File>(f) {
private boolean isLeaf;
private boolean isFirstTimeChildren = true;
private boolean isFirstTimeLeaf = true;
@Override
public ObservableList<TreeItem<File>> getChildren() {
if (isFirstTimeChildren) {
isFirstTimeChildren = false;
super.getChildren().setAll(buildChildren(this));
}
return super.getChildren();
}
@Override
public boolean isLeaf() {
if (isFirstTimeLeaf) {
isFirstTimeLeaf = false;
File f = (File) getValue();
isLeaf = f.isFile();
}
return isLeaf;
}
private ObservableList<TreeItem<File>> buildChildren(
TreeItem<File> TreeItem) {
File f = TreeItem.getValue();
if (f == null) {
return FXCollections.emptyObservableList();
}
if (f.isFile()) {
return FXCollections.emptyObservableList();
}
File[] files = f.listFiles();
if (files != null) {
ObservableList<TreeItem<File>> children = FXCollections
.observableArrayList();
for (File childFile : files) {
children.add(createNode(childFile));
}
return children;
}
return FXCollections.emptyObservableList();
}
};
}
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Group(), 300, 300);
VBox vbox = new VBox();
TreeItem<File> root = createNode(new File("c:/"));
TreeView treeView = new TreeView<File>(root);
vbox.getChildren().add(treeView);
((Group) scene.getRoot()).getChildren().add(vbox);
stage.setScene(scene);
stage.show();
}
}
上面的代码生成以下结果。
以下代码显示了如何使用用户域模型数据与TreeView。
创建Employee类以捕获用户域模型,并且代码使用循环将所有员工添加到树视图。
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Main extends Application {
List<Employee> employees = Arrays.<Employee>asList(
new Employee("a1", "A"),
new Employee("a2", "A"),
new Employee("e1", "E"));
private final Node rootIcon = new ImageView(new Image(getClass().getResourceAsStream("root.png")));
TreeItem<String> rootNode = new TreeItem<String>("Root",rootIcon);
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) {
rootNode.setExpanded(true);
for (Employee employee : employees) {
TreeItem<String> empLeaf = new TreeItem<String>(employee.getName());
boolean found = false;
for (TreeItem<String> depNode : rootNode.getChildren()) {
if (depNode.getValue().contentEquals(employee.getDepartment())){
depNode.getChildren().add(empLeaf);
found = true;
break;
}
}
if (!found) {
TreeItem depNode = new TreeItem(employee.getDepartment());
rootNode.getChildren().add(depNode);
depNode.getChildren().add(empLeaf);
}
}
stage.setTitle("Tree View Sample");
VBox box = new VBox();
final Scene scene = new Scene(box, 400, 300);
scene.setFill(Color.LIGHTGRAY);
TreeView<String> treeView = new TreeView<String>(rootNode);
treeView.setShowRoot(true);
treeView.setEditable(true);
box.getChildren().add(treeView);
stage.setScene(scene);
stage.show();
}
public static class Employee {
private final SimpleStringProperty name;
private final SimpleStringProperty department;
private Employee(String name, String department) {
this.name = new SimpleStringProperty(name);
this.department = new SimpleStringProperty(department);
}
public String getName() {
return name.get();
}
public void setName(String fName) {
name.set(fName);
}
public String getDepartment() {
return department.get();
}
public void setDepartment(String fName) {
department.set(fName);
}
}
}
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Main extends Application {
List<Employee> employees = Arrays.<Employee>asList(
new Employee("Jacob Smith", "Accounts Department"),
new Employee("Judy Mayer", "IT Support"),
new Employee("Gregory Smith", "IT Support"));
TreeItem<String> rootNode =
new TreeItem<>("MyCompany Human Resources");
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) {
rootNode.setExpanded(true);
for (Employee employee : employees) {
TreeItem<String> empLeaf = new TreeItem<>(employee.getName());
boolean found = false;
for (TreeItem<String> depNode : rootNode.getChildren()) {
if (depNode.getValue().contentEquals(employee.getDepartment())){
depNode.getChildren().add(empLeaf);
found = true;
break;
}
}
if (!found) {
TreeItem depNode = new TreeItem(employee.getDepartment());
rootNode.getChildren().add(depNode);
depNode.getChildren().add(empLeaf);
}
}
stage.setTitle("Tree View Sample");
VBox box = new VBox();
final Scene scene = new Scene(box, 400, 300);
scene.setFill(Color.LIGHTGRAY);
TreeView<String> treeView = new TreeView<>(rootNode);
treeView.setEditable(true);
treeView.setCellFactory((TreeView<String> p) ->
new TextFieldTreeCellImpl());
box.getChildren().add(treeView);
stage.setScene(scene);
stage.show();
}
private final class TextFieldTreeCellImpl extends TreeCell<String> {
private TextField textField;
private final ContextMenu addMenu = new ContextMenu();
public TextFieldTreeCellImpl() {
MenuItem addMenuItem = new MenuItem("Add Employee");
addMenu.getItems().add(addMenuItem);
addMenuItem.setOnAction((ActionEvent t) -> {
TreeItem newEmployee =
new TreeItem<>("New Employee");
getTreeItem().getChildren().add(newEmployee);
});
}
@Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
setText(null);
setGraphic(textField);
textField.selectAll();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(getTreeItem().getGraphic());
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(getTreeItem().getGraphic());
if (
!getTreeItem().isLeaf()&&getTreeItem().getParent()!= null
){
setContextMenu(addMenu);
}
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setOnKeyReleased((KeyEvent t) -> {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(textField.getText());
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
public static class Employee {
private final SimpleStringProperty name;
private final SimpleStringProperty department;
private Employee(String name, String department) {
this.name = new SimpleStringProperty(name);
this.department = new SimpleStringProperty(department);
}
public String getName() {
return name.get();
}
public void setName(String fName) {
name.set(fName);
}
public String getDepartment() {
return department.get();
}
public void setDepartment(String fName) {
department.set(fName);
}
}
}
上面的代码生成以下结果。
单元工厂可以向TreeView中的单个TreeItem添加具有特殊功能的TreeCell。
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Main extends Application {
List<Employee> employees = Arrays.<Employee> asList(new Employee(
"Jacob Smith", "Accounts Department"), new Employee("Isabella Johnson",
"Accounts Department"), new Employee("Mike Graham", "IT Support"),
new Employee("Judy Mayer", "IT Support"), new Employee("Gregory Smith",
"IT Support"));
TreeItem<String> rootNode;
public static void main(String[] args) {
Application.launch(args);
}
public Main() {
this.rootNode = new TreeItem<>("MyCompany Human Resources");
}
@Override
public void start(Stage stage) {
rootNode.setExpanded(true);
for (Employee employee : employees) {
TreeItem<String> empLeaf = new TreeItem<>(employee.getName());
boolean found = false;
for (TreeItem<String> depNode : rootNode.getChildren()) {
if (depNode.getValue().contentEquals(employee.getDepartment())) {
depNode.getChildren().add(empLeaf);
found = true;
break;
}
}
if (!found) {
TreeItem<String> depNode = new TreeItem<>(employee.getDepartment());
rootNode.getChildren().add(depNode);
depNode.getChildren().add(empLeaf);
}
}
stage.setTitle("Tree View Sample");
VBox box = new VBox();
final Scene scene = new Scene(box, 400, 300);
scene.setFill(Color.LIGHTGRAY);
TreeView<String> treeView = new TreeView<>(rootNode);
treeView.setEditable(true);
treeView
.setCellFactory((TreeView<String> p) -> new TextFieldTreeCellImpl());
box.getChildren().add(treeView);
stage.setScene(scene);
stage.show();
}
private final class TextFieldTreeCellImpl extends TreeCell<String> {
private TextField textField;
public TextFieldTreeCellImpl() {
}
@Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
setText(null);
setGraphic(textField);
textField.selectAll();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(getTreeItem().getGraphic());
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(getTreeItem().getGraphic());
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setOnKeyReleased((KeyEvent t) -> {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(textField.getText());
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
public static class Employee {
private final SimpleStringProperty name;
private final SimpleStringProperty department;
private Employee(String name, String department) {
this.name = new SimpleStringProperty(name);
this.department = new SimpleStringProperty(department);
}
public String getName() {
return name.get();
}
public void setName(String fName) {
name.set(fName);
}
public String getDepartment() {
return department.get();
}
public void setDepartment(String fName) {
department.set(fName);
}
}
}
上面的代码生成以下结果。
我们可以使用以下树单元编辑器。
有些类扩展了TreeCell实现来渲染单元格内的特定控件。
下面的代码创建一个带有复选框树项目的树视图。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<>("A");
rootItem.setExpanded(true);
TreeView tree = new TreeView(rootItem);
tree.setEditable(true);
tree.setCellFactory(CheckBoxTreeCell.forTreeView());
CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<>("a");
rootItem.getChildren().add(checkBoxTreeItem);
checkBoxTreeItem = new CheckBoxTreeItem<>("b");
rootItem.getChildren().add(checkBoxTreeItem);
tree.setRoot(rootItem);
StackPane root = new StackPane();
root.getChildren().add(tree);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
上面的代码生成以下结果。
Java面向对象设计 -Java继承和构造函数构造函数不是类的成员,它们不是由子类继承的。它们用于初始化实例变量。class CSuper {pu...
Java isLowerCase() 方法JavaCharacter类isLowerCase() 方法用于判断指定字符是否为小写字母。语法boolean isLowerCase(char ch)...
Java 实例 - 如何编译 Java 文件 Java 实例本文我们演示如何编译 HelloWorld.java 文件,其中 Java 代码如下:public class Hell...