12

Is it possible to change order of Nodes in JavaFX2 children list? I tried set() and Collections.swap() however both throw IllegalArgumentException in Parent as in some point the children list contains the same item at two positions (when node is at new position and has not been removed from the old position). There are flags inside Parent which JavaFX uses internaly in toFront() and toBack() which prevents the exception, however there is no way to access them from outside.

java.lang.IllegalArgumentException: Children: duplicate children added: parent = HBox@1424bf0
    at javafx.scene.Parent$1.onProposedChange(Parent.java:307)
    at com.sun.javafx.collections.VetoableObservableList.set(VetoableObservableList.java:156)
    at com.sun.javafx.collections.ObservableListWrapper.set(ObservableListWrapper.java:281)
    at java.util.Collections.swap(Collections.java:532)
Mariusz Jamro
  • 30,615
  • 24
  • 120
  • 162

2 Answers2

23

You can move the child in the parent's children list by

childNode.toFront();
childNode.toBack();
Uluk Biy
  • 48,655
  • 13
  • 146
  • 153
  • 1
    If using toFront() or toBack(), you may want to try both as I tried toFront() on a button within an HBox and this placed it to the right of the Label in the HBox. This behavior was counterintuitive to me – amartin7211 May 22 '17 at 18:45
9
ObservableList<Node> workingCollection = FXCollections.observableArrayList(pane.getChildren());
Collections.swap(workingCollection, 0, 1);
pane.getChildren().setAll(workingCollection);

Refer to this code:

package swapnode;

import java.util.Collection;
import java.util.Collections;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/**
 *
 * @author reegan
 */
public class SwapNode extends Application {

    @Override
    public void start(Stage primaryStage) {
        VBox root = new VBox(20);
        /* Thid Part Swap Children of Node */
        Pane pane = view();
        ObservableList<Node> workingCollection = FXCollections.observableArrayList(pane.getChildren());
        Collections.swap(workingCollection, 0, 1);
        pane.getChildren().setAll(workingCollection);

        root.getChildren().addAll(view(),pane);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * The main() method is ignored in correctly deployed JavaFX application.
     * main() serves only as fallback in case the application can not be
     * launched through deployment artifacts, e.g., in IDEs with limited FX
     * support. NetBeans ignores main().
     *
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    public Pane view() {
        HBox pane = new HBox(10);
        Button button = new Button("Hello");
        TextField field = new TextField("World");
        pane.getChildren().addAll(button,field);
        return pane;
    }
}
Adam Jensen
  • 541
  • 1
  • 10
  • 25
Reegan Miranda
  • 2,879
  • 6
  • 43
  • 55
  • 1
    Also make sure to use Platform.runLater() if executing the code from outside JavaFX thread ! – klonq Nov 18 '16 at 22:02