Search code examples
javajavafxjavafx-8javafx-2

Java Fx resizing scene to stage


I searched but could not find anything close to the problem that I am having with Fx. I am using Java Fx/JDK 8 and having problems with resizing the scene(s). The below code below loads only one screen at a time in scene graph, and switches between the screens. The problem is when I resize the stage. The scene is not being resized with the stage. Nothing fancy in FXML files only anchor pane and a few components.Thanks in advance.

public class ScreensFramework extends Application {

    static String main = "main";
    static String mainFile = "Main.fxml";
    static String play = "play";
    static String playFile = "Play.fxml";


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

    @Override
    public void start(Stage mainStage) {
        ScreensController mainContainer = new ScreensController();
        mainContainer.loadScreen(ScreensFramework.main, ScreensFramework.mainFile);
        mainContainer.loadScreen(ScreensFramework.play, ScreensFramework.playFile);

        mainContainer.setScreen(ScreensFramework.main);

        AnchorPane root = new AnchorPane();
        root.getChildren().setAll(mainContainer);
        Scene scene = new Scene(root);
        mainStage.setScene(scene);
        //This did not work out either
        mainStage.heightProperty().addListener((observable, oldValue, newValue) -> {
        root.getScene().prefHeight((double) newValue);
        });
        mainStage.show();
    }
}

public class MainController implements Initializable, ControlledScreen {

    ScreensController myController;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }

    public void setScreenParent(ScreensController screenParent){
        myController = screenParent;
    }
}

public class PlayController implements Initializable, ControlledScreen {

    ScreensController myController;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }

    public void setScreenParent(ScreensController screenParent){
        myController = screenParent;
    }
}


public class ScreensController extends AnchorPane {

    private HashMap<String, Node> screens = new HashMap<>();

    public void addScreen(String name, Node screen) {
        screens.put(name, screen);
    }

    public boolean loadScreen(String name, String resource) {
        try {
            FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
            Parent loadScreen = (Parent) myLoader.load();
            ControlledScreen myScreenControler = ((ControlledScreen) myLoader.getController());
            myScreenControler.setScreenParent(this);
            addScreen(name, loadScreen);
            return true;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return false;
        }
    }

     public boolean setScreen(final String name) {

        if (screens.get(name) != null) {    
            if (!getChildren().isEmpty()) {    
                getChildren().remove(0);                    //remove the displayed screen
                getChildren().add(0, screens.get(name));     //add the screen

            } else {
                getChildren().add(screens.get(name));  
            }
            return true;
        } else {
            return false;
        }               
    }       
}

Solution

  • You don't set the anchors for mainContainer or it's children. This way mainContainer simply is resized to it's preferred size and the children are resized to their preferred sizes. prefHeight() does not assign the preferred height, but calculates it.

    Assigning preferred sizes is not necessary though, if you use the anchor properties:

    AnchorPane.setTopAnchor(mainContainer, 0d);
    AnchorPane.setRightAnchor(mainContainer, 0d);
    AnchorPane.setBottomAnchor(mainContainer, 0d);
    AnchorPane.setLeftAnchor(mainContainer, 0d);
    
    public void addScreen(String name, Node screen) {
        screens.put(name, screen);
        AnchorPane.setTopAnchor(screen, 0d);
        AnchorPane.setRightAnchor(screen, 0d);
        AnchorPane.setBottomAnchor(screen, 0d);
        AnchorPane.setLeftAnchor(screen, 0d);
    }
    

    Using StackPanes instead of AnchorPanes (both as scene root and as supertype of ScreensController) would be much simpler though, since it resizes the children without the need to specify anchors.