在JavaFX表中按功能分组

时间:2016-06-11 20:39:41

标签: javafx javafx-8

我们正在将swt / nattable应用程序迁移到新的java8和Javafx8。

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

按功能划分的群组如何在Nattable中使用。

表本身有两个主要组件,不同列的dropzone。当用户将列拖到dropzone时,该表将该列的值组合在一起(如SQL中的Group by)。之后,该表将按操作显示该组的结果。

2 个答案:

答案 0 :(得分:2)

我只能解释"分组"在表格中,根据您想要分组的字段执行稳定的项目排序。

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

这是一个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

拖动&#34;颜色&#34;表格列标题为&#34;分组&#34;:

enter image description here

答案 1 :(得分:2)

在看了James_D的看法之后,我找到了一种方法来实现我正在寻找的功能。这里是我在JavaFX中的功能的完整源代码。

public class Main extends Application {

    List<Employee> employees = Arrays.<Employee>asList(
            new Employee("Ethan Williams", "ethan.williams@example.com", "A"),
            new Employee("Emma Jones", "emma.jones@example.com", "B"),
            new Employee("Michael Brown", "michael.brown@example.com", "A"),
            new Employee("Anna Black", "anna.black@example.com", "C"),
            new Employee("Rodger York", "roger.york@example.com", "B"),
            new Employee("Susan Collins", "susan.collins@example.com", "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);
    }
}