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.
source to share
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);
}
}
source to share