您的位置 首页 java

JavaFX 树视图

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方法或使用它的构造函数来创建一个图形图标到树项目。 图标的建议大小为16×16。

对根项目调用的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类以捕获用户域模型,并且代码使用循环将所有员工添加到树视图。

/*
 * 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.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);
 }
 }
}
 

新树项目按需

/*
 * 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.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。

/*
 * 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.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);
 }
 }
}
 

上面的代码生成以下结果。

树单元编辑

我们可以使用以下树单元编辑器。

  • CheckBoxTreeCell
  • ChoiceBoxTreeCell
  • ComboBoxTreeCell
  • TextFieldTreeCell

有些类扩展了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();
 }
}
 

上面的代码生成以下结果。

文章来源:智云一二三科技

文章标题:JavaFX 树视图

文章地址:https://www.zhihuclub.com/179260.shtml

关于作者: 智云科技

热门文章

网站地图