在TreeView
或TreeTableView
树中的所有节点必须是相同类型的。这使得你想要的设计(这是非常自然的)是一种痛苦。基本上,您必须将TreeView
或TreeTableView
的类型设置为树中所需的所有行类型的最具体的超类:即在此情况下,TreeTableView
的类型必须是Employee
和Factory
的超类。然后,列上的单元格值工厂必须对行对象进行类型测试以确定要返回的值。
拥有一个对象模型并不常见,其中这些对象模型通过继承而不是两者都是Object
的子类,因此您可能在这里需要TreeTableView<Object>
。
因此粗略地说(如果你使用普通的旧JavaBean风格的,而不是推荐JavaFX properties),你会用填充它定义像
TreeTableView<Object> treeTable = new TreeTableView<>();
treeTable.setShowRoot(false);
TreeTableColumn<Object, String> nameColumn = new TreeTableColumn<>("Name");
nameColumn.setCellValueFactory(cellData -> {
TreeItem<Object> rowItem = cellData.getValue();
if (rowItem != null && (rowItem.getValue() instanceof Factory)) {
Factory f = (Factory) rowItem.getValue() ;
return new SimpleStringProperty(f.getName());
} else {
return new SimpleStringProperty("");
}
});
TreeTableColumn<Object, Number> sizeColumn = new TreeTableColumn<>("Size");
sizeColumn.setCellValueFactory(cellData -> {
TreeItem<Object> rowItem = cellData.getValue();
if (rowItem != null && (rowItem.getValue() instanceof Factory)) {
Factory f = (Factory) rowItem.getValue() ;
return new SimpleObjectProperty<Number>(Double.valueOf(f.getSize()));
} else {
return new SimpleObjectProperty<Number>(null);
}
});
TreeTableColumn<Object, String> employeeColumn = new TreeTableColumn<>("Employee");
employeeColumn.setCellValueFactory(cellData -> {
TreeItem<Object> rowItem = cellData.getValue();
if (rowItem != null && (rowItem.getValue() instanceof Employee)) {
Employee emp = (Employee) rowItem.getValue() ;
return new SimpleStringProperty(emp.getName());
} else {
return new SimpleStringProperty("");
}
});
treeTable.getColumns().addAll(nameColumn, sizeColumn, employeeColumn);
当然
// fully initialized list of factories, with employee lists initialized:
List<Factory> factories = ... ;
TreeItem<Object> root = new TreeItem<>(null);
for (Factory factory : factories) {
TreeItem<Object> factoryItem = new TreeItem<>(factory);
root.getChildren().add(factoryItem);
for (Employee emp : factory.getEmployees()) {
TreeItem<Object> employeeItem = new TreeItem<>(emp);
factoryItem.getChildren().add(employeeItem);
}
}
treeTable.setRoot(root);
这是一个简单的SSCCE使用这个:
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
public class TreeTableExample extends Application {
@Override
public void start(Stage primaryStage) {
TreeTableView<Object> treeTable = new TreeTableView<>();
treeTable.setShowRoot(false);
TreeTableColumn<Object, String> nameColumn = new TreeTableColumn<>("Name");
nameColumn.setCellValueFactory(cellData -> {
TreeItem<Object> rowItem = cellData.getValue();
if (rowItem != null && (rowItem.getValue() instanceof Factory)) {
Factory f = (Factory) rowItem.getValue() ;
return new SimpleStringProperty(f.getName());
} else {
return new SimpleStringProperty("");
}
});
TreeTableColumn<Object, Number> sizeColumn = new TreeTableColumn<>("Size");
sizeColumn.setCellValueFactory(cellData -> {
TreeItem<Object> rowItem = cellData.getValue();
if (rowItem != null && (rowItem.getValue() instanceof Factory)) {
Factory f = (Factory) rowItem.getValue() ;
return new SimpleObjectProperty<Number>(Double.valueOf(f.getSize()));
} else {
return new SimpleObjectProperty<Number>(null);
}
});
TreeTableColumn<Object, String> employeeColumn = new TreeTableColumn<>("Employee");
employeeColumn.setCellValueFactory(cellData -> {
TreeItem<Object> rowItem = cellData.getValue();
if (rowItem != null && (rowItem.getValue() instanceof Employee)) {
Employee emp = (Employee) rowItem.getValue() ;
return new SimpleStringProperty(emp.getName());
} else {
return new SimpleStringProperty("");
}
});
treeTable.getColumns().addAll(nameColumn, sizeColumn, employeeColumn);
List<Factory> factories = createData();
TreeItem<Object> root = new TreeItem<>(null);
for (Factory factory : factories) {
TreeItem<Object> factoryItem = new TreeItem<>(factory);
root.getChildren().add(factoryItem);
for (Employee emp : factory.getEmployees()) {
TreeItem<Object> employeeItem = new TreeItem<>(emp);
factoryItem.getChildren().add(employeeItem);
}
}
treeTable.setRoot(root);
Scene scene = new Scene(treeTable, 800, 800);
primaryStage.setScene(scene);
primaryStage.show();
}
private List<Factory> createData() {
String[][] empNames = {
{"John", "Jane", "Mary"},
{"Susan", "Mike"},
{"Alex", "Francois", "Joanne"}
};
List<Factory> factories = new ArrayList<>();
for (String[] emps : empNames) {
int count = factories.size()+1 ;
Factory f = new Factory("Factory "+ count, count*10);
for (String empName : emps) {
f.getEmployees().add(new Employee(empName));
}
factories.add(f);
}
return factories ;
}
public static class Employee {
private String name ;
public Employee(String name) {
this.name = name ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Factory {
private String name ;
private double size ;
private List<Employee> employees ;
public Factory(String name, double size) {
this.name = name ;
this.size = size ;
this.employees = new ArrayList<>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSize() {
return size;
}
public void setSize(double size) {
this.size = size;
}
public List<Employee> getEmployees() {
return employees;
}
}
public static void main(String[] args) {
launch(args);
}
}
另一种方法,我认为这是一个有点做作,是创建表示在表视图行类,然后利用它Factory
和Employee
子类:
public abstract class EmploymentEntity {
public String getName() {
return null ;
}
public Double getSize() {
return null ;
}
public String getEmployeeName {
return null ;
}
}
然后
public class Employee extends EmploymentEntity {
private String name ;
public Employee(String name) {
this.name = name ;
}
@Override
public String getEmployeeName() {
return name ;
}
public void setEmployeeName(String name) {
this.name = name ;
}
}
和
public class Factory extends EmploymentEntity {
private String name ;
private double size ;
private List<Employee> employees ;
public Factory(String name, double size) {
this.name = name ;
this.size = size ;
this.employees = new ArrayList<>();
}
@Override
public String getName() {
return name ;
}
public void setName(String name) {
this.name = name ;
}
@Override
public Double getSize() {
return size ;
}
public void setSize(double size) {
this.size = size ;
}
public List<Employee> getEmployees() {
return employees ;
}
}
此对象模型确实是不自然的(对我来说,反正),但它确实使该表更容易一些:
TreeTableView<EmploymentEntity> treeTable = new TreeTableView<>();
TreeTableColumn<EmploymentEntity, String> nameColumn = new TreeTableColumn<>("Name");
nameColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getValue().getName()));
TreeTableColumn<EmploymentEntity, Number> sizeColumn = new TreeTableColumn<>("Size");
sizeColumn.setCellValueFactory(cellData -> new SimpleObjectProperty<Number>(cellData.getValue().getValue().getSize()));
TreeTableColumn<EmploymentEntity, String> employeeColumn = new TreeTableColumn<>("Employee");
employeeColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getValue().getEmployeeName()));
// etc...
通过“折叠”你在下拉的意思吗? –
我不知道是否有可能以这种确切的方式,你可以做类似的事情,看到每个记录的工厂名称和大小重复 – MaglioniLorenzo