1

Can a default Javafx table sort on multiple fields by dragging the columns on a dropzone?

My user need to select one or multiple columns to sort on different columns. The application is fully written in Java8 with JavaFX.

The source code that I now use is:

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);
    }
}

2 Answers 2

10

I view the TableView API and found that the JavaFX table does have a default implementation of this. Just click on the columns using the shift key.

Sign up to request clarification or add additional context in comments.

1 Comment

This just saved me from reinventing the wheel.
0

You can sort TableView on multiple columns by using getSortOrder(). See below.

col1.setSortable(true);
col2.setSortable(true);
tableView.getSortOrder().addAll(col1,col2);
col1.setSortType(TableColumn.SortType.ASCENDING);
col2.setSortType(TableColumn.SortType.ASCENDING);
tableView.sort();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.