文档



JavaFX:使用JavaFX UI组件

15 树表视图

本章介绍了TreeTableView用户界面组件,它是一个设计用来帮助您可视化无限层次的数据的控件,以列的形式呈现。

TreeTableView组件与TreeViewTableView控件有很多共同之处:它结合并扩展了它们的一些功能。

图15-1 TreeTableView组件示例

图15-1 TreeTableView组件示例的描述
图15-1 TreeTableView组件示例的描述

创建TreeTableView控件

在应用程序中创建一个基本的TreeTableView组件可以通过以下步骤完成:

  1. 创建树节点。

  2. 创建根元素。

  3. 将树节点添加到根元素。

  4. 创建一个或多个列。

  5. 定义单元格内容。

  6. 创建一个TreeTableView。

  7. 将列分配给TreeTableView。

在某些情况下,您可以省略或隐藏根元素。示例15-1实现了这些步骤来创建一个简单的TreeTableView控件。

示例15-1 带有一个列的TreeTableView

import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableColumn.CellDataFeatures;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
 
public class TreeTableViewSample extends Application {
 
    public static void main(String[] args) {
        Application.launch(args);
    }
    
    @Override
    public void start(Stage stage) {
        stage.setTitle("Tree Table View Samples");
        final Scene scene = new Scene(new Group(), 200, 400);
        Group sceneRoot = (Group)scene.getRoot();  
      
        //创建树节点
        final TreeItem<String> childNode1 = new TreeItem<>("子节点1");
        final TreeItem<String> childNode2 = new TreeItem<>("子节点2");
        final TreeItem<String> childNode3 = new TreeItem<>("子节点3");
        
        //创建根元素
        final TreeItem<String> root = new TreeItem<>("根节点");
        root.setExpanded(true);   
     
        //将树节点添加到根元素
        root.getChildren().setAll(childNode1, childNode2, childNode3);        

        //创建一个列
        TreeTableColumn<String,String> column = new TreeTableColumn<>("列");
        column.setPrefWidth(150);   
     
        //定义单元格内容
        column.setCellValueFactory((CellDataFeatures<String, String> p) -> 
            new ReadOnlyStringWrapper(p.getValue().getValue()));  

        //创建一个TreeTableView
        final TreeTableView<String> treeTableView = new TreeTableView<>(root);
        treeTableView.getColumns().add(column);
        treeTableView.setPrefWidth(152);
        treeTableView.setShowRoot(true);             
        sceneRoot.getChildren().add(treeTableView);
        stage.setScene(scene);
        stage.show();
    }     
}

为该列定义的单元格工厂指定了每个树项中要放置到该列中的内容。

当您编译并运行示例15-1时,它会产生如图15-2所示的输出。

图15-2 简单的TreeTableView组件

图15-2的描述
"图15-2 简单的TreeTableView组件"的描述

创建了一个简化的树视图组件,只有一列,而在您的应用程序中,通常会使用扩展的数据集。下一节将向您展示如何表示来自树视图用例的销售部门员工的个人数据。

添加多列

扩展在树视图章节中描述的用例,并提供有关销售部门每个员工的更多信息。展示了如何添加列。

示例15-2 创建一个带有两列的TreeTableView组件

import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
 
public class TreeTableViewSample extends Application {
 
    List<Employee> employees = Arrays.<Employee>asList(
        new Employee("Ethan Williams", "ethan.williams@example.com"),
        new Employee("Emma Jones", "emma.jones@example.com"),
        new Employee("Michael Brown", "michael.brown@example.com"),
        new Employee("Anna Black", "anna.black@example.com"),
        new Employee("Rodger York", "roger.york@example.com"),
        new Employee("Susan Collins", "susan.collins@example.com"));

    private final ImageView depIcon = new ImageView (
            new Image(getClass().getResourceAsStream("department.png"))
    );

    final TreeItem<Employee> root = 
        new TreeItem<>(new Employee("销售部门", ""), depIcon);
    public static void main(String[] args) {
        Application.launch(TreeTableViewSample.class, args);
    }

    @Override
    public void start(Stage stage) {
        root.setExpanded(true);
        employees.stream().forEach((employee) -> {
            root.getChildren().add(new TreeItem<>(employee));
        });
        stage.setTitle("树表视图示例");
        final Scene scene = new Scene(new Group(), 400, 400);
        scene.setFill(Color.LIGHTGRAY);
        Group sceneRoot = (Group) scene.getRoot();

        TreeTableColumn<Employee, String> empColumn = 
            new TreeTableColumn<>("员工");
        empColumn.setPrefWidth(150);
        empColumn.setCellValueFactory(
            (TreeTableColumn.CellDataFeatures<Employee, String> param) -> 
            new ReadOnlyStringWrapper(param.getValue().getValue().getName())
        );

        TreeTableColumn<Employee, String> emailColumn = 
            new TreeTableColumn<>("电子邮件");
        emailColumn.setPrefWidth(190);
        emailColumn.setCellValueFactory(
            (TreeTableColumn.CellDataFeatures<Employee, String> param) -> 
            new ReadOnlyStringWrapper(param.getValue().getValue().getEmail())
        );

        TreeTableView<Employee> treeTableView = new TreeTableView<>(root);
        treeTableView.getColumns().setAll(empColumn, emailColumn);
        sceneRoot.getChildren().add(treeTableView);
        stage.setScene(scene);
        stage.show();
    }
 
    public class Employee {
 
        private SimpleStringProperty name;
        private SimpleStringProperty email;
        public SimpleStringProperty nameProperty() {
            if (name == null) {
                name = new SimpleStringProperty(this, "name");
            }
            return name;
        }
        public SimpleStringProperty emailProperty() {
            if (email == null) {
                email = new SimpleStringProperty(this, "email");
            }
            return email;
        }
        private Employee(String name, String email) {
            this.name = new SimpleStringProperty(name);
            this.email = new SimpleStringProperty(email);
        }
        public String getName() {
            return name.get();
        }
        public void setName(String fName) {
            name.set(fName);
        }
        public String getEmail() {
            return email.get();
        }
        public void setEmail(String fName) {
            email.set(fName);
        }
    }
}

示例15-2中,您修改了Employee类中的数据结构,并定义了两个属性,分别对应员工的姓名和电子邮件地址。 TreeTableView组件提供了两列来表示它们。

检查示例15-3中显示的代码片段。 它为两列创建了单元格工厂。 setCellValueFactory方法为每列定义了TreeItem内容,以便Employee列包含Employee.name属性值,Email列包含Employee.email属性值。

示例15-3 实现Employee和Email列的单元格工厂

//用于Employee列的数据的单元格工厂
        empColumn.setCellValueFactory(
            (TreeTableColumn.CellDataFeatures<Employee, String> param) -> 
            new ReadOnlyStringWrapper(param.getValue().getValue().getName())
        );
        //用于Email列的数据的单元格工厂
        emailColumn.setCellValueFactory(
            (TreeTableColumn.CellDataFeatures<Employee, String> param) -> 
            new ReadOnlyStringWrapper(param.getValue().getValue().getEmail())
        );

当您从示例15-2编译和运行应用程序时,将显示图15-3中的输出。

图15-3 带有Employee和Email列的TreeTableView组件

图15-3的描述如下
"图15-3 带有Employee和Email列的TreeTableView组件"的描述

树表的默认样式强制所有树元素展开并显示所有表列。 但是,您可以使用TreeTableViewTreeTableColumn类的相应属性和方法来更改这些和其他默认设置。

修改可视外观

您可以启用显示表格菜单按钮,以便应用程序的用户可以切换表格列的可见性。调用treeTableView.setTableMenuButtonVisible(true);方法来设置treeTableView对象。该方法会在表头添加"+"按钮。用户隐藏"Employee"列时,图15-4捕捉到了这一刻。

图15-4 启用表格菜单按钮的TreeTableView

图15-4的描述
"图15-4 启用表格菜单按钮的TreeTableView"的描述

您还可以使用TreeTableView类的setShowRoot方法来控制根树项的可见性:treeTableView.setShowRoot(false);。传递给它的false值会隐藏根项,如图15-5所示。

图15-5 不带根树项的TreeTableView控件

图15-5的描述
"图15-5 不带根树项的TreeTableView控件"的描述

您可以通过点击列标题并切换排序模式(从升序到降序或反之亦然)来对列中的数据进行排序。除了内置的排序支持外,还可以通过示例15-4中列出的TreeTableColumnTreeTableView属性进行数据排序。

示例15-4 排序模式设置

//设置Email列的降序排序模式
emailColumn.setSortType(TreeTableColumn.SortType.DESCENDING);
//设置Email列的升序排序模式
emailColumn.setSortType(TreeTableColumn.SortType.ASCENDING);
//将排序模式应用于所有树项
treeTableView.setSortMode(TreeSortMode.ALL_DESCENDANTS);
//将排序模式仅应用于一级节点
treeTableView.setSortMode(TreeSortMode.ONLY_FIRST_LEVEL);

管理选择模式

TreeTableView类的默认选择模型是在MultipleSelectionModel抽象类中定义的,该类将默认值定义为SelectionMode.SINGLE。要启用树项和单元格的多重选择,请使用setSelectionModelsetCellSelectionEnabled方法的组合。有关可用值和结果行为的更多信息,请参见表15-1

表15-1 选择模型设置

setSelectionModel setCellSelectionEnabled 行为

SelectionMode.SINGLE

false

允许选择表中的单个行。

SelectionMode.SINGLE

true

允许选择表中的单个单元格。

SelectionMode.MULTUPLE

false

允许选择表中的多个行。

SelectionMode.MULTIPLE

true

允许选择多个行中的多个单元格。


例如,您可以实现对TreeTableView组件中的多个行和多个单元格进行选择,如示例15-5所示。

示例15-5 启用单元格的多选

treeTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
treeeTableView.getSelectionModel().setCellSelectionEnabled(true);

图15-6展示了在TreeTableViewSample应用程序的代码中添加这些行后可以选择的单元格。

图15-6 表格单元格的多选

图15-6的描述
"图15-6 表格单元格的多选"的描述

由于TreeTableView控件封装了表格视图和树视图的所有功能,您可能希望查看表格视图树视图章节以获取更多关于其他功能的信息。

相关文档 

关闭窗口

目录

JavaFX:使用JavaFX UI组件

展开 折叠