How to properly switch scenes / change the root node of a scene in JavaFX without FXML?

I am learning javafx and I already have the basics, so I want to do a slightly more complex project. I have read a lot of online guides on this topic, but I cannot find anywhere how to switch scenes or change the root node when each class represents 1 scene.
To understand better here, this is a simplified version of my project:
Let's say I have 3 classes A, B and C:

public class A{
    private Stage stage;
    A(Stage stage){
         this.stage = stage;
    }
    public void showGui(){
        // This will make all elements, put them on scene and then set that scene to stage
    }
    public void callB(){
        B b = new B(Stage);
        b.showGui();
    }
} 
public class B{
    private Stage stage;
    B(Stage stage){
         this.stage = stage;
    }
    public void showGui(){
        // This will make all elements, put them on scene and then set that scene to stage
    }
    public void callC(){
        C c = new C(Stage);
        c.showGui();
    }
} 
public class C{
  // This is completely same as other two, it calls A so those 3 form some sort of circle.  
}

      

When running the program inside public void start (Stage primaryStage) I make object A and pass it as main, then in each class I change it and it works fine. But I have few questions about it:
Is this the correct way to do it?
Is there any other way to do this while keeping the classes, or should I just do everything inside the main class?
Is it better to pass the scene and then change the root nodes?

Sorry if I ask too much, but I read a lot about this but could not find anything that could help me, so this is my last solution.

+3


source to share


1 answer


There are several design improvements you can pursue here:

  • Your classes don't need to know about Stage

    other classes at all, see the hidden concept - the less they know is that your program is less complex. The root node of the scene will suffice. You can even override node to avoid extra code.

  • Your classes look very similar. You might want to introduce a parent abstract class and delegate all switching logic to one method (so you wouldn't need to change all classes if your logic changed)



See the following example:

public class FxThreeNodes extends Application {

    private abstract class CycledView extends StackPane { // Choose whatever is most appropriate class
        CycledView(CycledView next) {
            this.next = next;

            createGUI();
        }

        abstract void createGUI();

        protected void callNext() {
            getScene().setRoot(next);
        }

        private CycledView next;
    }

    // Here you implement diffent GUIs for A, B and C
    private class A extends CycledView { 

        public A(CycledView next) {
            super(next);
        }

        void createGUI() {
            getChildren().add(new Button("I'm A") {
                @Override
                public void fire() {
                    callNext();
                }

            });
        }

    }

    private class B extends CycledView { 

        public B(CycledView next) {
            super(next);
        }

        void createGUI() {
            getChildren().add(new Button("This is B") {
                @Override
                public void fire() {
                    callNext();
                }

            });
        }

    }

    private class C extends CycledView { 

        public C(CycledView next) {
            super(next);
        }

        void createGUI() {
            getChildren().add(new Button("Greeting from C") {
                @Override
                public void fire() {
                    callNext();
                }

            });
        }

    }


    @Override
    public void start(Stage primaryStage) {

        CycledView c = new C(null);
        CycledView b = new B(c);
        CycledView a = new A(b);
        c.next = a;

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

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

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

      

+3


source







All Articles