JavaFX UI控件教程(十四)之Tree View
翻译自 Tree View
在本章中,您将学习如何在JavaFX应用程序中构建树结构,向树视图添加项,处理事件以及通过实现和应用单元工厂来自定义树单元。
包的TreeView
类javafx.scene.control
提供了层次结构的视图。在每个树中,层次结构中的最高对象称为“根”。根包含几个子项,也可以有子项。没有孩子的项目称为“叶子”。
图13-1显示了具有树视图的应用程序的屏幕截图。
创建树视图
在JavaFX应用程序中构建树结构时,通常需要实例化TreeView
类,定义多个TreeItem
对象,使其中一个树项成为根,将根添加到树视图中,将其他树项添加到根中。
您可以使用相应的TreeItem
类构造函数或通过调用setGraphic
方法,使用图形图标来附加每个树项。图标的建议大小为16x16,但事实上,任何Node
对象都可以设置为图标,并且它将是完全交互式的。
例13-1是具有根和五个叶子的简单树视图的实现。
import javafx.application.Application;
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.StackPane;
import javafx.stage.Stage;public class TreeViewSample extends Application {private final Node rootIcon = new ImageView(new Image(getClass().getResourceAsStream("folder_16.png")));public static void main(String[] args) {launch(args);}@Overridepublic void start(Stage primaryStage) {primaryStage.setTitle("Tree View Sample"); TreeItem<String> rootItem = new TreeItem<String> ("Inbox", rootIcon);rootItem.setExpanded(true);for (int i = 1; i < 6; i++) {TreeItem<String> item = new TreeItem<String> ("Message" + i); rootItem.getChildren().add(item);} TreeView<String> tree = new TreeView<String> (rootItem); StackPane root = new StackPane();root.getChildren().add(tree);primaryStage.setScene(new Scene(root, 300, 250));primaryStage.show();}
}
for
通过调用getChildren
和add
方法将循环中创建的所有树项添加到根项。您也可以使用该addAll
方法而不是add
方法一次包含所有先前创建的树项。
如示例13-1所示,您可以在TreeView
创建新TreeView
对象时在类的构造函数中指定树的根,也可以通过调用类的方法来设置它。setRoot
TreeView
与TreeView
类不同,TreeItem
该类不扩展Node
类。因此,您无法应用任何视觉效果或向树项目添加菜单。使用单元工厂机制克服此障碍,并根据应用程序的需要为树项定义尽可能多的自定义行为。
实现Cell工厂
细胞工厂机制被用于生成TreeCell
实例来表示单个TreeItem
的TreeView
。当您的应用程序使用动态更改或按需添加的过多数据进行操作时,使用单元工厂尤其有用。
考虑一个可视化给定公司的人力资源数据的应用程序,并使用户能够修改员工详细信息并添加新员工。
例13-2创建了Employee
类,并根据各自的部门安排员工。
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
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.paint.Color;
import javafx.stage.Stage;import javafx.beans.property.SimpleStringProperty;
import javafx.scene.layout.VBox;public class TreeViewSample extends Application {private final Node rootIcon = new ImageView(new Image(getClass().getResourceAsStream("root.png")));private final Image depIcon = new Image(getClass().getResourceAsStream("department.png"));List<Employee> employees = Arrays.<Employee>asList(new Employee("Ethan Williams", "Sales Department"),new Employee("Emma Jones", "Sales Department"),new Employee("Michael Brown", "Sales Department"),new Employee("Anna Black", "Sales Department"),new Employee("Rodger York", "Sales Department"),new Employee("Susan Collins", "Sales Department"),new Employee("Mike Graham", "IT Support"),new Employee("Judy Mayer", "IT Support"),new Employee("Gregory Smith", "IT Support"),new Employee("Jacob Smith", "Accounts Department"),new Employee("Isabella Johnson", "Accounts Department"));TreeItem<String> rootNode = new TreeItem<String>("MyCompany Human Resources", rootIcon);public static void main(String[] args) {launch(args);}@Overridepublic 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<String> depNode = new TreeItem<String>(employee.getDepartment(), new ImageView(depIcon));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);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);}}
}
使用示例13-2,您可以预览树视图及其项目,但不能更改现有项目或添加任何新项目。例13-3显示了实现单元工厂的应用程序的修改版本。修改后的应用程序使您可以更改员工的姓名。
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Node;
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.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;import javafx.beans.property.SimpleStringProperty;
import javafx.scene.layout.VBox;public class TreeViewSample extends Application {private final Node rootIcon = new ImageView(new Image(getClass().getResourceAsStream("root.png")));private final Image depIcon = new Image(getClass().getResourceAsStream("department.png"));List<Employee> employees = Arrays.<Employee>asList(new Employee("Ethan Williams", "Sales Department"),new Employee("Emma Jones", "Sales Department"),new Employee("Michael Brown", "Sales Department"),new Employee("Anna Black", "Sales Department"),new Employee("Rodger York", "Sales Department"),new Employee("Susan Collins", "Sales Department"),new Employee("Mike Graham", "IT Support"),new Employee("Judy Mayer", "IT Support"),new Employee("Gregory Smith", "IT Support"),new Employee("Jacob Smith", "Accounts Department"),new Employee("Isabella Johnson", "Accounts Department"));TreeItem<String> rootNode = new TreeItem<String>("MyCompany Human Resources", rootIcon);public static void main(String[] args) {Application.launch(args);}@Overridepublic 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<String> depNode = new TreeItem<String>(employee.getDepartment(), new ImageView(depIcon));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.setEditable(true);treeView.setCellFactory(new Callback<TreeView<String>,TreeCell<String>>(){@Overridepublic TreeCell<String> call(TreeView<String> p) {return new TextFieldTreeCellImpl();}});box.getChildren().add(treeView);stage.setScene(scene);stage.show();}private final class TextFieldTreeCellImpl extends TreeCell<String> {private TextField textField;public TextFieldTreeCellImpl() {}@Overridepublic void startEdit() {super.startEdit();if (textField == null) {createTextField();}setText(null);setGraphic(textField);textField.selectAll();}@Overridepublic void cancelEdit() {super.cancelEdit();setText((String) getItem());setGraphic(getTreeItem().getGraphic());}@Overridepublic 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(new EventHandler<KeyEvent>() {@Overridepublic void handle(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);}}
}
setCellFactory
调用该treeView
对象的方法会覆盖TreeCell
实现并重新定义TextFieldTreeCellImpl
类中指定的树项。
在TextFieldTreeCellImpl
类创建了一个TextField
针对每个树对象,并提供方法来处理编辑事件。
请注意,必须setEditable(true)
在树视图上显式调用该方法才能编辑其所有项目。
编译并运行例13-3中的应用程序。然后尝试单击树中的员工并更改其名称。图13-4显示了在IT支持部门编辑树项目的时刻。
按需添加新树项
修改Tree View Sample应用程序,以便人力资源代表可以添加新员工。使用示例13-4的粗体代码行作为参考。这些行将上下文菜单添加到与部门对应的树项目中。选择“添加员工”菜单项后,新树项将作为叶添加到当前部门。
使用此isLeaf
方法可以区分部门树项和员工树项。
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Node;
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.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;import javafx.beans.property.SimpleStringProperty;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.VBox;public class TreeViewSample extends Application {private final Node rootIcon = new ImageView(new Image(getClass().getResourceAsStream("root.png")));private final Image depIcon = new Image(getClass().getResourceAsStream("department.png"));List<Employee> employees = Arrays.<Employee>asList(new Employee("Ethan Williams", "Sales Department"),new Employee("Emma Jones", "Sales Department"),new Employee("Michael Brown", "Sales Department"),new Employee("Anna Black", "Sales Department"),new Employee("Rodger York", "Sales Department"),new Employee("Susan Collins", "Sales Department"),new Employee("Mike Graham", "IT Support"),new Employee("Judy Mayer", "IT Support"),new Employee("Gregory Smith", "IT Support"),new Employee("Jacob Smith", "Accounts Department"),new Employee("Isabella Johnson", "Accounts Department"));TreeItem<String> rootNode = new TreeItem<String>("MyCompany Human Resources", rootIcon);public static void main(String[] args) {Application.launch(args);}@Overridepublic 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(), new ImageView(depIcon));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.setEditable(true);treeView.setCellFactory(new Callback<TreeView<String>,TreeCell<String>>(){@Overridepublic TreeCell<String> call(TreeView<String> p) {return new TextFieldTreeCellImpl();}});box.getChildren().add(treeView);stage.setScene(scene);stage.show();}private final class TextFieldTreeCellImpl extends TreeCell<String> {private TextField textField;private ContextMenu addMenu = new ContextMenu();public TextFieldTreeCellImpl() {MenuItem addMenuItem = new MenuItem("Add Employee");addMenu.getItems().add(addMenuItem);addMenuItem.setOnAction(new EventHandler() {public void handle(Event t) {TreeItem newEmployee = new TreeItem<String>("New Employee");getTreeItem().getChildren().add(newEmployee);}});}@Overridepublic void startEdit() {super.startEdit();if (textField == null) {createTextField();}setText(null);setGraphic(textField);textField.selectAll();}@Overridepublic void cancelEdit() {super.cancelEdit();setText((String) getItem());setGraphic(getTreeItem().getGraphic());}@Overridepublic 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(new EventHandler<KeyEvent>() {@Overridepublic void handle(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);}}
}
编译并运行应用程序。然后在树结构中选择一个部门并右键单击它。出现上下文菜单,如图13-5所示。
从上下文菜单中选择“添加员工”菜单项时,新记录将添加到当前部门。图13-6显示了添加到Accounts Department的新树项。
由于已为树项启用了编辑,因此可以将默认的“新员工”值更改为相应的名称。
使用树单元格编辑器
开始的JavaFX SDK 2.2,可以使用可用下面的树单元格编辑器的API中:CheckBoxTreeCell
,ChoiceBoxTreeCell
,ComboBoxTreeCell
,TextFieldTreeCell
。类扩展了TreeCell
实现以在单元内呈现特定控件。
例13-5演示了CheckBoxTreeCell
在UI中使用类来构建复选框的层次结构。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;public class TreeViewSample extends Application {public static void main(String[] args) {launch(args);}@Overridepublic void start(Stage primaryStage) {primaryStage.setTitle("Tree View Sample"); CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("View Source Files");rootItem.setExpanded(true); final TreeView tree = new TreeView(rootItem); tree.setEditable(true);tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView()); for (int i = 0; i < 8; i++) {final CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<String>("Sample" + (i+1));rootItem.getChildren().add(checkBoxTreeItem); }tree.setRoot(rootItem);tree.setShowRoot(true);StackPane root = new StackPane();root.getChildren().add(tree);primaryStage.setScene(new Scene(root, 300, 250));primaryStage.show();}
}
编译并运行Example 13-5,然后选择View Source Files项。您应该看到如图13-7所示的输出,其中选择了所有子项。
要使CheckBoxTreeItem
实例独立,请使用以下setIndependent
方法:rootItem.setIndependent(true);
。
运行TreeViewSample应用程序时,其行为应如图13-8所示进行更改。
TreeView
TreeItem
TreeCell
Cell
TextField
CheckBoxTreeCell
CheckBoxTreeItem
JavaFX UI控件教程(十四)之Tree View相关推荐
- JavaFX UI控件教程(四)之Button
翻译自 Button Button通过JavaFX API提供的类使开发人员能够在用户单击按钮时处理操作.该Button班是的扩展Labeled类.它可以显示文本,图像或两者.图3-1显示了具有各种 ...
- JavaFX UI控件教程(二)之JavaFX UI控件
翻译自 JavaFX UI控件 本章概述了通过API提供的JavaFX UI控件. JavaFX UI控件是使用场景图中的节点构建的.因此,控件可以使用JavaFX平台的视觉丰富功能.由于JavaF ...
- JavaFX UI控件教程(一)之简述
翻译自 JavaFX UI控件概述 关于本教程 本教程介绍JavaFX API中提供的内置JavaFX UI控件. 该文件包含以下章节: JavaFX UI控件 标签 按钮 单选按钮 切换按钮 复选 ...
- JavaFX UI控件教程(八)之Choice Box
翻译自 Choice Box 本章介绍了选项框,这些UI控件提供了在几个选项之间快速选择的支持. 使用ChoiceBox该类将选择框添加到JavaFX应用程序.其简单的实现如图7-1所示. 图7- ...
- JavaFX UI控件教程(二十八)之UI控件的自定义
翻译自 Customization of UI Controls 本章介绍了UI控件自定义的各个方面,并总结了Oracle提供的一些提示和技巧,以帮助您修改UI控件的外观和行为. 您可以通过应用层叠 ...
- JavaFX UI控件教程(二十二)之Titled Pane和Accordion
翻译自 Titled Pane and Accordion 本章介绍如何在JavaFX应用程序中使用accordion和title窗格的组合. 标题窗格是带标题的面板.它可以打开和关闭,它可以封装任 ...
- JavaFX UI控件教程(二十)之HTML Editor
翻译自 HTML Editor 在本章中,您将学习如何使用嵌入式HTML编辑器编辑JavaFX应用程序中的文本. 该HTMLEditor控件是一个功能齐全的富文本编辑器.它的实现基于HTML5的文档 ...
- JavaFX UI控件教程(十八)之Progress Bar和Progress Indicator
翻译自 Progress Bar and Progress Indicator 在本章中,您将了解进度指示器和进度条,以及可视化JavaFX应用程序中任何操作进度的UI控件. 本ProgressIn ...
- JavaFX UI控件教程(十六)之Separator
翻译自 Separator 本章介绍如何使用分隔符组织JavaFX应用程序的UI组件. SeparatorJavaFX API中可用的类表示水平或垂直分隔线.它用于划分应用程序用户界面的元素,不会产 ...
最新文章
- AI 生成的代码可信吗?编写的代码有 Bug 吗?
- js控制input框输入数字时,累计求和
- Powerdesigner 在线打开 不用安装客户端 访问pdm,ldm文件
- 12-order by和group by 原理和优化 sort by 倒叙
- html div bgcolor,HTML body bgcolor transparent
- SQL Server 自动循环归档分区数据脚本
- DOM 事件深入浅出(一)
- HTTP传递数据的几种方法
- 用html制作学生个人博客,网页制作论坛(学生个人网页制作代码)
- epic注册什么服务器最好,epic国内有服务器吗(epic服务器在哪)
- 实现折叠的uitableviewcell效果
- Leetcode(24)——两两交换链表中的节点
- 蚂蚁森林中能量自动收取
- word保存为html不压缩图片大小,教你怎样从word中提取图片以及缩小图片大小
- 2021-07-04
- 高性能无线综合测试仪 无线电综合测试仪 ---TFN PM5100 100KHz-1GHz
- 干货|对于软件产品质量的一些思考
- 攻防世界高手进阶区 ——forgot
- 本月腾讯,阿里,美团等技术团队的精品文章推送
- 行为验证码(AJ-Captcha快速入门)
热门文章
- 『软件工程9』结构化系统分析——解决软件“做什么”问题
- [mybatis]映射文件_select_resultMap_关联查询
- [JavaWeb-Servlet]Servlet相关配置
- MongoDB 分片
- 大话数据结构学习笔记二:算法
- Ubuntu 上不了网
- Spring cloud Loadbalance
- Java修炼之路——基础篇——平台无关性
- 牛客小白月赛11:Rinne Loves Data Structure
- Infinite Fraction Path UVALive - 8207