I have got a JavaFX 2.2 FlowPane and want it's children to be change their order on demand.
I found out that
Collections.sort( getChildren(), new Comparator(){...} );
causes the exception
java.lang.IllegalArgumentException: Children: duplicate children added: parent = ...
I also tried to sort using the child Nodes toFront() method (as suggested here How to change order of children in JavaFX), but this does not seem to influence the list order.
Is there anything else I could try or are children in a scene graph unmutable regarding their order?
FlowPane – lays out its children in a flow that wraps at the flowpane's boundary. HBox – arranges its content nodes horizontally in a single row. VBox – arranges its content nodes vertically in a single column.
If we use Grid Pane in our application, all the nodes that are added to it are arranged in a way that they form a grid of rows and columns.
HBox is a subclass of Pane that lays out its children next to each other, in a horizontal row. VBox is a subclass of Pane that lays out its children in vertical column. An HBox might be used as the bottom component in a BorderPane, making it possible to line up several components along the bottom of the border pane.
The Scene it self can only have one root Pane. So if you want 2 panes in the Scene you need 3.
Update: Errata
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 the JavaFX 2.x bug:
When I run your program, the list does not update until I resize the window horizontally (vertically does not do anything) - jdk 7u25 / Windows 7 x64.
The bug is fixed in Java 8, so if you use Java 8, the sample solution will work.
Solution Strategy
Code Snippet
ObservableList<Node> workingCollection = FXCollections.observableArrayList(
flow.getChildren()
);
Collections.sort(workingCollection, new NodeComparator());
flow.getChildren().setAll(workingCollection);
Sample Output
Sample output before sorting:
Sample output after sorting:
Sample Application
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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With