2016-09-20 8 views
0


табличного дерево: Отображение различных типов данных

У меня есть 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 должен быть суперклассом как 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); 
    } 
} 

enter image description here


Другой подход, который я думаю, это немного искусственно, чтобы создать класс, представляющий строку в виде таблицы, а затем сделать 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... 
+0

. Модификация этого использования объекта для представления строки таблицы, которая содержит Employee and Factory, добиться того же упрощения таблицы. Это не требует изменения модели данных для расширения общего предка и устраняет необходимость в литье и т. Д., Требуемое для версии Object. – Geoff

+0

@Geoff Это выглядит неплохой идеей. Однако я не вижу чистого способа реализовать фабрики сотовой стоимости; он избегает тестирования типа, но логика все равно будет довольно грязной (если я не упускаю что-то, что, безусловно, возможно). –

+0

Это было бы по существу то же самое, что и ваше второе решение, которое я думал, но вместо того, чтобы объекты домена спускались из общего класса, класс-оболочка сделал бы это с одной реализацией для каждого объекта домена. Заводы сотовой стоимости будут идентичны вашим. Это означало бы больше классов, которые были бы недостатком, поэтому я думаю, что это зависит от того, какой недостаток предпочтительнее? – Geoff

Смежные вопросы