Dans un TreeView
ou TreeTableView
tous les nœuds dans l'arborescence doivent être du même type. Cela rend le type de design que vous voulez (ce qui est très naturel) quelque chose d'une douleur. Fondamentalement, vous devez faire le type de TreeView
ou TreeTableView
la superclasse la plus spécifique de tous les types de lignes que vous voulez dans l'arbre: dans ce cas, le type de TreeTableView
doit être une superclasse à la fois Employee
et Factory
. Ensuite, les fabriques de valeurs de cellule sur les colonnes devront taper les objets de ligne pour déterminer quelle valeur renvoyer.
Il serait inhabituel d'avoir un modèle d'objet dans lequel ceux-ci étaient liés par héritage autre que les deux étant des sous-classes de Object
, donc vous avez probablement besoin d'un TreeTableView<Object>
ici.
Donc, grosso modo (si vous utilisez le style ancien JavaBean plaine, au lieu du recommandé JavaFX properties), vous définiriez quelque chose comme
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);
et bien sûr vous le remplissiez avec
// 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);
Voici un simple SSCCE utilisant ceci:
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);
}
}
![enter image description here](https://i.stack.imgur.com/IsiJR.png)
Une autre approche, que je pense est un peu artificielle, est de créer une classe représentant la ligne de la vue de la table, puis de faire des sous-classes Factory
et Employee
de celui-ci:
public abstract class EmploymentEntity {
public String getName() {
return null ;
}
public Double getSize() {
return null ;
}
public String getEmployeeName {
return null ;
}
}
puis
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 ;
}
}
et
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 ;
}
}
Ce modèle d'objet est vraiment contre nature (pour moi, de toute façon), mais il ne fait la table un peu plus facile:
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...
par « fold » voulez-vous dire dans un menu déroulant? –
Je ne sais pas si c'est possible de cette façon, vous pouvez faire quelque chose de similaire en voyant le nom de l'usine et la taille répétée pour chaque enregistrement – MaglioniLorenzo