2016-06-11 29 views
0

我们正在将swt/nattable应用程序迁移到新的java8和Javafx8。在JavaFX表中按功能分组

一切都很顺利,但无法找到nattable的一个功能。我们正在搜索的功能是“group by”功能。因此,我们需要一个库/实现来拖放标签上的列,并将这些列在表中分组。有人可以帮助我们吗?

按功能分组如何在Nattable中工作。

表格本身和不同列的dropzone有两个主要组件。当用户将列拖动到dropzone时,表将该列的值分组在一起(如在SQL中分组)。在那之后,表格将通过操作显示该组的结果。

+0

对于那些不熟悉nattable的人,你能更全面地解释它的功能吗? –

+0

增加了一些更多细节描述。 – JimmyD

回答

1

看了之后James_D的e我找到了一种通过我正在寻找的功能实现该组的功能。这里是JavaFX中按功能分组的完整源代码。

public class Main extends Application { 

    List<Employee> employees = Arrays.<Employee>asList(
      new Employee("Ethan Williams", "[email protected]", "A"), 
      new Employee("Emma Jones", "[email protected]", "B"), 
      new Employee("Michael Brown", "[email protected]", "A"), 
      new Employee("Anna Black", "[email protected]", "C"), 
      new Employee("Rodger York", "[email protected]", "B"), 
      new Employee("Susan Collins", "[email protected]", "A")); 

    final TreeItem<Employee> root = 
      new TreeItem<>(new Employee("Sales Department", "", ""), null); 

    Label dropLabel; 

    BreadCrumbBar breadcrum; 

    private Comparator<Employee> groupingComparator; 

    private ArrayList<String> comperatorList = new ArrayList<>(); 

    Map<String, Function<Employee, Comparable>> gettersMap = new HashMap<>(); 

    private TreeTableView<Employee> treeTableView; 

    @Override 
    public void start(Stage stage) throws Exception{ 


     stage.setTitle("Tree Table View Sample"); 
     final Scene scene = new Scene(new Group(), 400, 400); 
     scene.setFill(Color.LIGHTGRAY); 
     Group sceneRoot = (Group) scene.getRoot(); 


     root.setExpanded(true); 
     employees.stream().forEach((employee) -> { 
      root.getChildren().add(new TreeItem<>(employee)); 
     }); 

     gettersMap.put("Employee", Employee::getName); 
     gettersMap.put("Email", Employee::getEmail); 
     gettersMap.put("Test", Employee::getTest); 

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

     TreeTableColumn<Employee, String> emailColumn = column("Email", Employee::getEmail); 
     emailColumn.setPrefWidth(190); 
     emailColumn.setCellValueFactory(
       (TreeTableColumn.CellDataFeatures<Employee, String> param) -> 
         new ReadOnlyStringWrapper(param.getValue().getValue().getEmail()) 
     ); 

     TreeTableColumn<Employee, String> testColumn = column("Test", Employee::getTest); 
     testColumn.setPrefWidth(190); 
     testColumn.setCellValueFactory(
       (TreeTableColumn.CellDataFeatures<Employee, String> param) -> 
         new ReadOnlyStringWrapper(param.getValue().getValue().getTest()) 
     ); 

     treeTableView = new TreeTableView<Employee>(root); 
     treeTableView.getColumns().setAll(empColumn, emailColumn, testColumn); 

     breadcrum = new BreadCrumbBar<>(); 

     breadcrum.setOnCrumbAction(new EventHandler<BreadCrumbBar.BreadCrumbActionEvent<String>>() { 
      @Override 
      public void handle(BreadCrumbBar.BreadCrumbActionEvent<String> event) { 
      } 
     }); 

     dropLabel = new Label("Use the shift key when you select a column to group"); 

     dropLabel.setOnDragOver(e -> { 
      if (groupingComparator != null && "Group".equals(e.getDragboard().getString())) { 
       e.acceptTransferModes(TransferMode.COPY); 
      } 
     }); 

     dropLabel.setOnDragDropped(e -> { 
      if (groupingComparator != null && "Group".equals(e.getDragboard().getString())) { 

       comperatorList.add(((Label) e.getGestureSource()).getText()); 

       String selectedColumn = ((Label)e.getGestureSource()).getText(); 

       if(breadcrum.selectedCrumbProperty().get() == null) { 

        TreeItem<String> root = new TreeItem<String>(selectedColumn); 

        breadcrum.selectedCrumbProperty().set(root); 
       } 
       else 
       { 
        TreeItem<String> root = (TreeItem<String>) breadcrum.selectedCrumbProperty().get(); 

        TreeItem<String> child = new TreeItem<String>(selectedColumn); 
        root.getChildren().add(child); 

        breadcrum.selectedCrumbProperty().set(child); 
       } 

       try { 

        String comperatorString = ""; 

        for (String temp : comperatorList) 
        { 
         comperatorString += temp + ";"; 
        } 

        comperatorString = comperatorString.substring(0, comperatorString.length()-1); 

        Comparator<Employee> comparator = getComparator(comperatorString); 

        ArrayList<Employee> allItems = new ArrayList<Employee>(); 
        getChildren(root, allItems); 

        Collections.sort(allItems, comparator); 

        ArrayList<String> compareValues = new ArrayList<String>(); 

        ArrayList<TreeItem<Employee>> parents = new ArrayList<TreeItem<Employee>>(); 
        parents.add(0, this.root); 

        this.root.getChildren().removeAll(this.root.getChildren()); 

        for(Employee item: allItems) 
        { 
         for(int i =0; i < comperatorList.size(); i++) 
         { 
          Method getMethod = item.getClass().getMethod("get" + this.comperatorList.get(i), null); 

          String result = (String) getMethod.invoke(item); 

          if((compareValues.size() <= i || !result.equals(compareValues.get(i)))) 
          { 
           TreeItem<Employee> newItem = new TreeItem<Employee>(new Employee()); 
           newItem.setExpanded(true); 

           parents.add(i+1, newItem); 

           parents.get(i).getChildren().add(newItem); 

           compareValues.add(i, result); 
          } 

          //Add leafs to tree 
          if(i == comperatorList.size() -1 || (i == 0 && comperatorList.size() == 0)) 
          { 
           parents.get(i+1).getChildren().add(new TreeItem<Employee>(item)); 
          } 


         } 
        } 

        treeTableView.setRoot(root); 

       } 
       catch (Exception ex) 
       { 
        System.out.print(ex.getStackTrace()); 
       } 

       e.setDropCompleted(true); 

      } 
     }); 
     VBox boxRoot = new VBox(); 

     boxRoot.getChildren().add(dropLabel); 
     boxRoot.getChildren().add(breadcrum); 
     boxRoot.getChildren().add(treeTableView); 

     treeTableView.setShowRoot(false); 
     treeTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 
     treeTableView.getSelectionModel().setCellSelectionEnabled(true); 

     sceneRoot.getChildren().add(boxRoot); 
     stage.setScene(scene); 
     stage.show(); 
    } 


    public ArrayList<Employee> getChildren(TreeItem<Employee> root, ArrayList<Employee> allItems) 
    { 
     for(TreeItem<Employee> employeeItem :root.getChildren()) 
     { 
      if(employeeItem.isLeaf()) 
      { 
       allItems.add(employeeItem.getValue()); 
      } 
      else 
      { 
       getChildren(employeeItem, allItems); 
      } 

     } 

     return allItems; 
    } 

    public Comparator<Employee> getComparator(String order){ 
     String[] keys = order.split(";"); 
     Comparator<Employee> result = Comparator.comparing(gettersMap.get(keys[0])); 
     for (int i = 1; i<keys.length; i++){ 
      result = result.thenComparing(gettersMap.get(keys[i])); 
     } 
     return result; 
    } 

    private <T extends Comparable<T>> TreeTableColumn<Employee,T> column(String title, Function<Employee,T> property) { 
     TreeTableColumn<Employee,T> col = new TreeTableColumn<>(); 
     //col.setCellValueFactory(cellData -> new SimpleObjectProperty<>(property.apply(cellData.getValue()))); 

     Label graphic = new Label(title); 
     graphic.setOnDragDetected(e -> { 
      groupingComparator = Comparator.comparing(property); 
      Dragboard dragboard = graphic.startDragAndDrop(TransferMode.COPY); 
      ClipboardContent cc = new ClipboardContent(); 
      cc.putString("Group"); 
      dragboard.setContent(cc); 
     }); 
     graphic.setOnDragDone(e -> { 
      groupingComparator = null ; 
     }); 

     col.setGraphic(graphic); 

     return col ; 
    } 


    public static void main(String[] args) { 
     launch(args); 
    } 
} 
1

我只能将表中的“分组”解释为对要分组的字段执行稳定的项目排序。

您只需在此设置拖放操作,以便当您从表格标题拖放到标签上时,表格的项目将按列表示的属性排序。唯一棘手的部分是没有简单的方法来访问表头:最简单的方法不是设置列文本,而是创建一个包含文本的标签并将列图形设置为该标签。这样你可以用标签注册拖动处理程序。

这里是一个SSCCE:

import java.util.Collections; 
import java.util.Comparator; 
import java.util.function.Function; 

import javafx.application.Application; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.input.ClipboardContent; 
import javafx.scene.input.Dragboard; 
import javafx.scene.input.TransferMode; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 

public class GroupByTable extends Application { 

    public enum Color { GREEN, BLUE, RED } 
    public enum Shape { RECTANGLE, CIRCLE, TRIANGLE } 
    public enum Size { SMALL, MEDIUM, LARGE } 


    private Label groupByLabel; 
    private Comparator<Item> groupingComparator ; 


    @Override 
    public void start(Stage primaryStage) { 
     TableView<Item> table = new TableView<>(); 

     table.getColumns().add(column("Size", Item::getSize)); 
     table.getColumns().add(column("Color", Item::getColor)); 
     table.getColumns().add(column("Shape", Item::getShape)); 

     groupByLabel = new Label("Grouping"); 

     groupByLabel.setOnDragOver(e -> { 
      if (groupingComparator != null && "grouping".equals(e.getDragboard().getString())) { 
       e.acceptTransferModes(TransferMode.COPY); 
      } 
     }); 

     groupByLabel.setOnDragDropped(e -> { 
      if (groupingComparator != null && "grouping".equals(e.getDragboard().getString())) { 
       table.getItems().sort(groupingComparator); 
       e.setDropCompleted(true); 
      } 
     }); 

     for (Color color : Color.values()) { 
      for (Size size : Size.values()) { 
       for (Shape shape : Shape.values()) { 
        table.getItems().add(new Item(color, shape, size)); 
       } 
      } 
     } 

     Collections.shuffle(table.getItems()); 

     BorderPane root = new BorderPane(table); 
     BorderPane.setAlignment(groupByLabel, Pos.CENTER); 
     BorderPane.setMargin(groupByLabel, new Insets(20)); 

     root.setTop(groupByLabel); 

     Scene scene = new Scene(root, 600, 600); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private <T extends Comparable<T>> TableColumn<Item,T> column(String title, Function<Item,T> property) { 
     TableColumn<Item,T> col = new TableColumn<>(); 
     col.setCellValueFactory(cellData -> new SimpleObjectProperty<>(property.apply(cellData.getValue()))); 

     Label graphic = new Label(title); 
     graphic.setOnDragDetected(e -> { 
      groupingComparator = Comparator.comparing(property); 
      Dragboard dragboard = graphic.startDragAndDrop(TransferMode.COPY); 
      ClipboardContent cc = new ClipboardContent(); 
      cc.putString("grouping"); 
      dragboard.setContent(cc); 
     }); 
     graphic.setOnDragDone(e -> { 
      groupingComparator = null ; 
     }); 

     col.setGraphic(graphic); 

     return col ; 
    } 

    public static class Item { 
     private final Color color ; 
     private final Shape shape ; 
     private final Size size ; 
     public Item(Color color, Shape shape, Size size) { 
      super(); 
      this.color = color; 
      this.shape = shape; 
      this.size = size; 
     } 
     public Color getColor() { 
      return color; 
     } 
     public Shape getShape() { 
      return shape; 
     } 
     public Size getSize() { 
      return size; 
     } 

     @Override 
     public String toString() { 
      return String.format("%s %s %s", size, color, shape); 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

初始屏幕截图:

enter image description here

拖动 “颜色” 表列标题为 “分组” 之后:

enter image description here

+0

当用户对一列进行分组时,是否也可以将该表替换为treeTableView(以便所有蓝色颜色在同一子树中)? – JimmyD

+0

是的:你需要重建树上的树结构。 –

+0

Tnx确实帮助我实现了我的群组功能。 – JimmyD