JavaFX - reordering children in FlowPane

I have JavaFX 2.2 FlowPane and want children to change their order on demand.

I found out that

Collections.sort( getChildren(), new Comparator(){...} ); 

throws an exception

 java.lang.IllegalArgumentException: Children: duplicate children added: parent = ... 

I also tried sorting using the child nodes method toFront () (as suggested here How to change the order of children in JavaFX ), but this does not seem to affect the list order.

Is there anything else I could try or are the children in the scene graph not questionable about their order?

+4
source share
1 answer

Update: Fix

Due to a bug in JavaFX 2.x, the sample solution for this answer will not work in JavaFX 2.x. Thanks to assylias for identifying JavaFX 2.x errors:

When I run your program, the list is not updated until I resize the window horizontally (does nothing vertically) - jdk 7u25 / Windows 7 x64.

The bug is fixed in Java 8, so if you use Java 8 , a sample solution will work.

Decision strategy

  • Create a new collection based on the children of the flow panel.
  • Sort a new collection.
  • Set the children of the stream to the contents of the sorted collection.

Code snippet

 ObservableList<Node> workingCollection = FXCollections.observableArrayList( flow.getChildren() ); Collections.sort(workingCollection, new NodeComparator()); flow.getChildren().setAll(workingCollection); 

Output result

Example output before sorting:

unsorted

Example output after sorting:

sorted

Application example

 import javafx.application.Application; import javafx.collections.*; import javafx.event.*; import javafx.geometry.Pos; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.stage.Stage; import java.util.*; public class FlowGo extends Application { private final ObservableList<Label> labels = FXCollections.observableArrayList( createLabel("oranges"), createLabel("apples"), createLabel("pears"), createLabel("peaches"), createLabel("bananas") ); @Override public void start(Stage stage) { FlowPane flow = createFlow(); VBox layout = new VBox(10); layout.getChildren().setAll( flow, createActionButtons(flow) ); layout.setAlignment(Pos.CENTER); layout.setStyle("-fx-padding: 10px; -fx-background-color: cornsilk;"); stage.setScene(new Scene(layout)); stage.show(); } private HBox createActionButtons(final FlowPane flow) { Button sort = new Button("Sort"); sort.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { ObservableList<Node> workingCollection = FXCollections.observableArrayList( flow.getChildren() ); Collections.sort(workingCollection, new NodeComparator()); flow.getChildren().setAll(workingCollection); } }); Button reset = new Button("Reset"); reset.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { flow.getChildren().setAll(labels); } }); HBox buttonBar = new HBox(10); buttonBar.getChildren().addAll( sort, reset ); buttonBar.setAlignment(Pos.CENTER); return buttonBar; } private FlowPane createFlow() { FlowPane flow = new FlowPane(); flow.setHgap(10); flow.setVgap(10); flow.getChildren().setAll(labels); flow.setAlignment(Pos.CENTER); flow.setStyle("-fx-padding: 10px; -fx-background-color: lightblue; -fx-font-size: 16px;"); return flow; } private Label createLabel(String text) { Label label = new Label(text); label.setUserData(text); return label; } public static void main(String[] args) { launch(args); } private static class NodeComparator implements Comparator<Node> { @Override public int compare(Node o1, Node o2) { String s1 = (String) o1.getUserData(); String s2 = (String) o2.getUserData(); return s1.compareTo(s2); } } } 
+6
source

Source: https://habr.com/ru/post/1501016/


All Articles