0

I am new to javaFX and have a beginner level understanding of java. I am trying to build a simple app that will eventually generate forms. I want to change scenes when a button is selected, but I am not sure how to do this, everything I have read is a bit above my level.`

@Override
public void start(Stage primaryStage) {

         primaryStage.setTitle("Welcome to the Log Book Generator");
         /*Defining Options on Home screen*/

         Button btnR = new Button("Repair");
         Button btnM = new Button("Maintenance");
         Button btnW = new Button("Weather");
         Button btnO = new Button ("Other");
         Button btnU = new Button ("Filter Pickup");
         Button btnVC = new Button ("Verification/Calibration");
         Button btnE = new Button ("Exit");



    /*Actions upon button selection*/    
    btnR.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Repair");
        }
    });
    btnM.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Maintenance");
        }
    });
    btnW.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Weather");
        }
    });
    btnO.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Other");
        }
    });
    btnU.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Filter Pickup");
        }
    });
    btnVC.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Verification/Calibration");
        }
    });
    btnE.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.exit(0);
        }
    });
    Pane root = new Pane();
    /*StackPane root = new StackPane();
    /* Setting Button Layout*/
    btnM.setLayoutX(150);btnM.setLayoutY(150);
    btnR.setLayoutX(150);btnR.setLayoutY(250);
    btnW.setLayoutX(150);btnW.setLayoutY(350);
    btnO.setLayoutX(150);btnO.setLayoutY(150);
    btnU.setLayoutX(150);btnU.setLayoutY(450);
    btnVC.setLayoutX(150);btnVC.setLayoutY(550);
    btnE.setLayoutX(350);btnE.setLayoutY(650);
    /*Ask user for Selection*/
    Label label;
    label = new Label("Please select a task.");
    label.setFont(Font.font("Arial", 32));            
    root.getChildren().add(label);
    root.getChildren().add(btnE);
    root.getChildren().add(btnVC);
    root.getChildren().add(btnU);
    root.getChildren().add(btnO);
    root.getChildren().add(btnW);
    root.getChildren().add(btnM);
    root.getChildren().add(btnR);
    primaryStage.setScene(new Scene(root, 500, 750));
    primaryStage.show();
}

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

} ` I am planning on making the different sections their own scene within the same stage. Any help would be appreciated. I am using NetBeans8.2.

Michael H.
  • 93
  • 3
  • 13
  • https://stackoverflow.com/questions/37200845/how-to-switch-scenes-in-javafx – SedJ601 Sep 13 '18 at 21:11
  • Not using FXML so that answer doesn't help. I am not passing any data between scenes so I don't see why I would use FXML. – Michael H. Sep 13 '18 at 22:24
  • What does passing data and fxml have to do with each other? – SedJ601 Sep 13 '18 at 22:40
  • Create a scene in each handler and then use primaryStage.setScene() – SedJ601 Sep 13 '18 at 22:41
  • From most of what I have been reading FXML is for passing data – Michael H. Sep 13 '18 at 22:49
  • Sedrick can you show me an example? – Michael H. Sep 13 '18 at 22:50
  • 2
    A `Scene`, as I understand it, affects the entire `Stage`, not just sections of it. If you're looking to replace certain sections of the window when a button is clicked, you'll want to use different containers, not scenes. – Zephyr Sep 13 '18 at 23:17
  • On an unrelated note: `FXML` really has nothing to do with passing data. It is a framework used to define an applications GUI layout. It can often simplify the process of designing and updating the UI for your application. When coupled with SceneBuilder, it can be a great way to design your application as you can see the results instantly, without needing to compile and run your code. – Zephyr Sep 13 '18 at 23:47
  • Another note: you are working way too hard to layout your buttons where you want them. Do some more research on JavaFX Containers. In particular, looks like a `VBox` would be much better for you here instead of a `StackPane`. – Zephyr Sep 13 '18 at 23:51

3 Answers3

5

Instead of trying to change the Scene, it looks like you just wish to update portions of the screen.

Below is a simple example of using a BorderPane for the root layout and then changing the content of the CENTER pane when a button is clicked.

The sample below just switches the content out for different labels, but you could just as easily use root.setCenter() to pass a whole VBox or HBox or any other populated container.

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

    private BorderPane root;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        primaryStage.setWidth(500);

        // Simple interface. The buttons will be on the left and the contents of the center section will change
        // when buttons are clicked.
        root = new BorderPane();
        root.setPadding(new Insets(10));

        // Create the left pane, containing buttons to switch the CENTER content
        VBox paneButtonBox = new VBox(5);
        paneButtonBox.setAlignment(Pos.TOP_CENTER);
        paneButtonBox.setPadding(new Insets(10));

        // Create 3 buttons to change the contents of the CENTER
        Button btnView1 = new Button("View 1");
        btnView1.setOnAction(e -> switchContent(1));
        Button btnView2 = new Button("View 2");
        btnView2.setOnAction(e -> switchContent(2));
        Button btnView3 = new Button("View 3");
        btnView3.setOnAction(e -> switchContent(3));

        // Add the Buttons to the button box
        paneButtonBox.getChildren().addAll(btnView1, btnView2, btnView3);

        // Add the button box to the LEFT of root pane
        root.setLeft(paneButtonBox);

        primaryStage.setScene(new Scene(root));

        primaryStage.show();
    }

    /**
     * @param view is the # of the content we want to display. For this sample, just to demonstrate.
     */
    private void switchContent(int view) {

        // Change the content of the CENTER node based on button clicked
        switch (view) {
            case 1:
                root.setCenter(new Label("THIS IS VIEW 1"));
                break;
            case 2:
                root.setCenter(new Label("THIS IS VIEW 2"));
                break;
            case 3:
                root.setCenter(new Label("THIS IS VIEW 3"));
                break;

        }

    }
}

The above code produces the following layout:

Screenshot

The Label on the right changes as each button is clicked. Hope this helps to lead you in the right direction.

The basic concept is to create a portion of your layout that you can change the contents of. BorderPane provides these sections for you, but you could also just create a separate VBox yourself and just call VBox.getChildren().addAll() and pass in whatever Node objects you want when you need to change the content.

Another Option

Another way of accomplishing a similar interface functionality would be to use a TabPane. Each Tab you add to the TabPane has a content property that you can use to set any nodes into that you choose, similar to how BorderPane works above:

@Override
public void start(Stage primaryStage) {

    primaryStage.setHeight(300);
    primaryStage.setWidth(500);

    TabPane root = new TabPane();

    // Create Separate Tabs
    Tab tab1 = new Tab("Section 1");
    tab1.setContent(new Label("This is Section 1!"));
    Tab tab2 = new Tab("Section 2");
    tab2.setContent(new Label("This is Section 2!"));
    Tab tab3 = new Tab("Section 3");
    tab3.setContent(new Label("This is Section 3!"));

    root.getTabs().addAll(tab1, tab2, tab3);

    primaryStage.setScene(new Scene(root));
    primaryStage.show();

}

And that result:

Screenshot

Zephyr
  • 9,885
  • 4
  • 28
  • 63
  • i'm up-voting this since it's more accurate and detailed but i'm not deleting my answer since it's the specific answer to his question about "change scene" – SDIDSA Sep 13 '18 at 23:50
  • Appreciate the upvote. The OP is new to Java and seems a bit confused, though, as he does specifically say he wants only a section of the stage to change. Changing the `Scene` would obviously affect the entire `Stage`. I definitely agree having both answers for now is best, though, as it's somewhat unclear what the OP really wants. – Zephyr Sep 13 '18 at 23:52
0

you can create your scenes, initialize them, and set them to the primary stage in the event handlers, just note that if you're trying to add children on top of each others vertically you should consider using a VBox, also if you want to add a multiple children into the same parent you can user addAll instead of add

that's the code you would have (i just did the first 3 scenes to show you how this works and you should be able to do the others accordingly)

// having a fixed size for the stage
double width = 500, height = 600;

// Creating scenes
Scene sceneR, sceneM, sceneW, sceneO, sceneU, sceneVC, mainMenu;

// saving the primaryStage to have access to it from other methods
Stage ps;

@Override
public void start(Stage primaryStage) {
    ps = primaryStage;

    //calling the initializing method
    initializeScenes();

    primaryStage.setTitle("Welcome to the Log Book Generator");
    /* Defining Options on Home screen */

    Button btnR = new Button("Repair");
    Button btnM = new Button("Maintenance");
    Button btnW = new Button("Weather");
    Button btnO = new Button("Other");
    Button btnU = new Button("Filter Pickup");
    Button btnVC = new Button("Verification/Calibration");
    Button btnE = new Button("Exit");

    /* Actions upon button selection */
    btnR.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            ps.setScene(sceneR);
        }
    });
    btnM.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            ps.setScene(sceneM);
        }
    });
    btnW.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            ps.setScene(sceneW);
        }
    });
    btnO.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Other");
        }
    });
    btnU.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Filter Pickup");
        }
    });
    btnVC.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Verification/Calibration");
        }
    });
    btnE.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.exit(0);
        }
    });

    // 20 will be the spacing
    VBox root = new VBox(40);
    root.setAlignment(Pos.CENTER);

    Label label;
    label = new Label("Please select a task.");
    label.setFont(Font.font("Arial", 32));

    // Adding buttons to the root
    root.getChildren().addAll(label, btnR, btnM, btnW, btnO, btnU, btnVC, btnE);

    btnE.setTranslateX(100);

    mainMenu = new Scene(root, width, height);
    primaryStage.setScene(mainMenu);
    primaryStage.show();
}

public void initializeScenes() {
    // You Can Here Add Whatever you want into your scenes

    // initializing the Repair Scene :

    VBox rootR = new VBox(10);
    rootR.setAlignment(Pos.CENTER);
    Label descR = new Label("Repair Scene");
    Button backR = new Button("back");
    rootR.getChildren().addAll(descR, backR);
    // the back button takes you back to the main menu scene
    backR.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            ps.setScene(mainMenu);
        }
    });
    sceneR = new Scene(rootR, width, height);

    // initializing the Maintenance Scene :

    VBox rootM = new VBox(10);
    rootM.setAlignment(Pos.CENTER);
    Label descM = new Label("Maintenance Scene");
    Button backM = new Button("back");
    rootM.getChildren().addAll(descM, backM);
    // the back button takes you back to the main menu scene
    backM.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            ps.setScene(mainMenu);
        }
    });
    sceneM = new Scene(rootM, width, height);

    // initializing the Weather Scene :

    VBox rootW = new VBox(10);
    rootW.setAlignment(Pos.CENTER);
    Label descW = new Label("Weather Scene");
    Button backW = new Button("back");
    rootW.getChildren().addAll(descW, backW);
    // the back button takes you back to the main menu scene
    backW.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            ps.setScene(mainMenu);
        }
    });
    sceneW = new Scene(rootW, width, height);



    // you should be able to do the other scenes
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}
SDIDSA
  • 894
  • 10
  • 19
-1
package principal;

public class Start extends Application {

    private static Stage stage;

    private static Scene parametrizacao;
    private static Scene monitorar;
    private static Scene relatorio;

    @Override
    public void start(Stage primaryStage) throws Exception {
        stage = primaryStage;

        primaryStage.setTitle("Java FX");

        Parent fxmlInicio = FXMLLoader.load(getClass().getResource("/fxml/inicio.fxml"));
        parametrizacao = new Scene(fxmlInicio);

        Parent fxmlMonitorar = FXMLLoader.load(getClass().getResource("/fxml/monitora.fxml"));
        monitorar = new Scene(fxmlMonitorar);

        Parent fxmlRelatorio = FXMLLoader.load(getClass().getResource("/fxml/relatorio.fxml"));
        relatorio = new Scene(fxmlRelatorio);

        primaryStage.setResizable(false);
        //stage.initStyle(StageStyle.UNDECORATED);
        //stage.getIcons().add(new Image(getClass().getResourceAsStream("/icone.jpg")));
        primaryStage.setScene(inicio);
        primaryStage.show();
    }

    //Metodo que faz a navegação entre as telas
    public static void changeScreen(String scr, Object userData) {
        switch (scr) {
            case "inicio":
                stage.setScene(inicio);
                break;
            case "monitorar":
                stage.setScene(monitorar);
                notifyAllListeners("monitorar", scr);
                break;
            case "relatorio":
                stage.setScene(relatorio);
                notifyAllListeners("relatorio", scr);
                break;
        }
    }

    public static void changeScreen(String scr) {
        changeScreen(scr, null);
    }

    public static void main(String[] args) {
        launch(args);
    }

    public static ArrayList<OnChangeScreen> listeners = new ArrayList<>();

    public static interface OnChangeScreen {

        void onChangeScreen(String newScreen, Object userData);
    }

    public static void addOnChangeScreenListener(OnChangeScreen newListener) {
        listeners.add(newListener);
    }

    public static void notifyAllListeners(String newScreen, Object userData) {
        for (OnChangeScreen l : listeners) {
            l.onChangeScreen(newScreen, userData);
        }
    }

}
O'Neil
  • 3,790
  • 4
  • 16
  • 30