2016-09-20 19 views
0


TreeTableView:

異なるデータ型を表示する私は、従業員のリストが含まれていFactoryクラスを持っています。私はTreeTableViewを使ってFactoryのデータを表示したいと思います。 Factoryの名前とサイズを表示するのはかなり先ですが、従業員の名前を表示する方法はわかりません。

public class Factory { 
     private String name; 
     private double size; 
     private List<Employee> employees; 

     public Factory(name, size){this.name=name; this.size=size} 

     // Getters & setters 

    } 

は、私は次のような出力を持つようにしたい:

enter image description here

possibiltyで工場を折るします。

+0

あなたがドロップダウンに意味ですか「折る」とは? –

+0

その正確な方法で可能かどうか分かりませんが、工場名とサイズを各レコードについて繰り返すことで同様のことができます。 – MaglioniLorenzo

答えて

3

TreeViewまたはTreeTableViewでは、ツリー内のすべてのノードが同じタイプでなければなりません。これはあなたが(非常に自然な)痛みのようなものになります。基本的には、TreeViewまたはTreeTableViewのタイプを、ツリー内で必要なすべてのタイプの行の中で最も特定のスーパークラスにする必要があります。つまり、TreeTableViewのタイプはEmployeeFactoryの両方のスーパークラスである必要があります。次に、列のセル値ファクトリは、行オブジェクトをテストして戻す値を決定する必要があります。

サブモデルがObject以外の継承によって関連づけられたオブジェクトモデルを使用することは珍しいので、ここではTreeTableView<Object>が必要です。 (あなたの代わりにお勧めJavaFX propertiesの、昔ながらのJavaBeanスタイルを使用している場合)、大まかに言えば

だから、あなたは

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); 
    } 
} 
public abstract class EmploymentEntity { 

    public String getName() { 
     return null ; 
    } 

    public Double getSize() { 
     return null ; 
    } 

    public String getEmployeeName { 
     return null ; 
    } 
} 


私は少し人工的だと思う別のアプローチは、テーブルビュー内の行を表すクラスを作成し、それをFactoryEmployeeサブクラスを作ることですその後、

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... 
+0

従業員と工場を含むテーブル行を表すオブジェクトを使用するこの変更テーブルの同じ単純化を達成する。これにより、共通の祖先を拡張するためにデータモデルを変更する必要はなく、Objectバージョンで必要なキャストなどの必要性がなくなります。 – Geoff

+0

@Geoffこれは良いアイデアのように見えます。私はセル値のファクトリを実装するためのきれいな方法を見ていません。それは型テストを避けますが、論理はかなり乱雑です(確かに私が何かを見落とさない限り、確かに可能です)。 –

+0

これは私が考えた2番目のソリューションと本質的に同じですが、ドメインオブジェクトを共通クラスから降下させる代わりに、各ドメインオブジェクトに対して1つの実装でラッパークラスが実行します。セルの値の工場はあなたと同じです。それは欠点となるより多くのクラスを意味するので、どちらの欠点が優先されるかによって異なります。 – Geoff

関連する問題