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