我们正在将swt / nattable应用程序迁移到新的java8和Javafx8。
一切顺利,但无法找到nattable的一个特征。我们正在搜索的功能是" group by"特征。因此,我们需要一个库/实现来拖放标签上的列,并在表格中将这些列分组。有人可以帮助我们吗?
按功能划分的群组如何在Nattable中使用。
表本身有两个主要组件,不同列的dropzone。当用户将列拖到dropzone时,该表将该列的值组合在一起(如SQL中的Group by)。之后,该表将按操作显示该组的结果。
答案 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);
}
}
初始截屏:
拖动&#34;颜色&#34;表格列标题为&#34;分组&#34;:
答案 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);
}
}