3

The title may be a bit vague, so allow me to define it a little better. I have a working piece of code (down below): a simple main menu for a game I am working on. Everything works well, except for the Start button.

What I want to be able to do is click the Start button, and have a new scene appear on the same stage (window). I do not want to see a new window open. I have talked with someone more experienced in Java, and they told me to create separate classes for the MenuFX and the GameFX. If that is the case, I would need to call some start or launch method on the GameFX class from the MenuFX class, correct? Is this the best approach, or would I want to keep all FX-related code in one class? Also, I should keep the same stage for all FX work, no?

This post shed some light on things, but I am not well-versed in some of the terms discussed- for instance, I still do not understand the concept of Root.

Also, this post talks about a similar application, but I am not using FXML or SceneBuilder... I do not know if any of it is relatable.

MenuFX.java - I have removed some of the working code, simply for brevity. You can see that all I need help with is tying the Start button to some functionality that makes a new empty scene.

/* 
 * This is simply working on the title screen.
 */

// Asssume all imports are correct
import java.everythingNeeded


public class MenuFX extends Application {
@Override

        public void start (Stage primaryStage) {

        // Make the window a set size...
        primaryStage.setResizable(false);


        // Create menu vbox and set the background image
        VBox menuVBox = new VBox(30);
        menuVBox.setBackground(new Background(new BackgroundImage(new 
        Image("image/bambooBG.jpg"), null, null, null, new BackgroundSize(45, 
        45, true, true, true, true))));



        // Create start button
        Button startButton = new Button("Start Game");

        // TODO Some things...
        // Need assistance here



        // Create help button
        Button helpButton = new Button("Help");
        helpButton.setOnAction(e -> THINGS);

        // Create music toggle button
        ToggleButton musicButton = new ToggleButton("Music On/Off");
        musicButton.setOnAction(e -> THINGS);

        // Create credits button
        Button creditsButton = new Button("Credits");
        creditsButton.setOnAction(THINGS);

        // Create exit button and set it to close the program when clicked
        Button endButton = new Button("Exit Game");
        endButton.setOnAction(e -> Platform.exit());

        // Add all nodes to the vbox pane and center it all
        // Must be in order from top to bottom
        menuVBox.getChildren().addAll(startButton, helpButton, musicButton, creditsButton, endButton);
        menuVBox.setAlignment(Pos.CENTER);

        // New scene, place pane in it
        Scene scene = new Scene(menuVBox, 630, 730);

        // Place scene in stage
        primaryStage.setTitle("-tiles-"); 
        primaryStage.setScene(scene); 
        primaryStage.show(); 
    }


    // Needed to run JavaFX w/o the use of the command line
    public static void main(String[] args) {

        launch(args);
    }

}

Restating: I want to click the Start button and have the currently open window change to an empty scene.

Here is a pastebin of the MenuFX class in its entirety: http://pastebin.com/n6XbQfhc

Thank you for any help,

Bagger

Community
  • 1
  • 1
  • It's not really clear what you're asking. Your `GameFX` class just has to either extend a node class of some type, or give access to a node instance. Then you can replace the root of the scene with that node when the button is pressed. [Here](http://stackoverflow.com/questions/32464698/java-how-do-i-start-a-standalone-application-from-the-current-one-when-both-are) is a post I answered a while back which seems to be sort-of-similar: that opens new windows for each class but you obviously don't have to do that. If that doesn't help, you probably need to clarify your question. – James_D Mar 16 '17 at 18:48
  • @James_D [This](http://stackoverflow.com/questions/36551431/can-you-write-two-different-java-fx-scenes-as-two-separate-classes?rq=1) post is very similar to my question. I just happened upon it. Also, I do not understand what Root is. I have seen it in many code samples but it seems too in-depth for me as of yet. I am sorry for sounding so ignorant, but I am practically teaching myself Java, specifically JavaFX. My instructor this semester seems to be a little unmotivated. –  Mar 16 '17 at 19:09
  • "Root" just refers to the root node of the scene graph, i.e the node that is displayed in the scene. The [Oracle tutorial](http://docs.oracle.com/javase/8/javafx/scene-graph-tutorial/scenegraph.htm#JFXSG107) has a description of "scene graph" terminology, with examples. (FWIW, claiming you are struggling because your instructor is no good is not going to get you much sympathy here. Many, if not most, of us come from an era where you had no choice but to be self-taught; and the primary audience for this site is professional programmers who do not have the luxury of someone to teach them.) – James_D Mar 16 '17 at 19:10
  • @James_D Well, I appreciate you helping me. I will work through it some more and see what can be done. I'll try not to clutter the site with my questions. –  Mar 16 '17 at 19:19
  • You're welcome to ask as many questions as you like: just make sure you do a reasonable amount of research first. I just did a google search for "JavaFX what is the root of the scene" and the documentation I linked came up as the first hit, with [this](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Scene.html) second, which is also somewhat useful. – James_D Mar 16 '17 at 19:29

1 Answers1

4

The basic idea here is you would do something like:

public class GameFX {

    private final BorderPane rootPane ; // or any other kind of pane, or  Group...

    public GameFX() {

        rootPane = new BorderPane();

        // build UI, register event handlers, etc etc

    }

    public Pane getRootPane() {
        return rootPane ;
    }

    // other methods you may need to access, etc...

}

Now back in the MenuFX class you would do

Button startButton = new Button("Start Game");
startButton.setOnAction(e -> {
    GameFX game = new GameFX();
    primaryStage.getScene().setRoot(game.getRootPane());
});
James_D
  • 201,275
  • 16
  • 291
  • 322
  • 1
    Note, if you don't have a reference to the stage, you can get the scene from the button in the action handler of the button. For example: `startButton.getScene().setRoot(game.getRootPane());`. – jewelsea Jan 10 '20 at 06:15