3
votes

I'm trying to build a single window application to get to know JavaFX better. It was quite nice and easy, until I did not get into the details...

I have an AnchorPane as a main container of the other GUI elements. I realized, that it is too high for my laptop screen (805 px high, 600 px wide), so I decided to put the AnchorPane inside a ScrollPane to have scroll bars, when I shrink the window. The AnchorPane is configured in FXML, the ScrollPane in Java source code.

The AnchorPane:

<AnchorPane maxHeight="805.0" prefHeight="805.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.jzoli.mp3checker.view.MainWindowController">

...

The ScrollPane:

public class ScrollableMainFrame extends ScrollPane {

public ScrollableMainFrame(Pane content) {
    super();

    // set scrollbar policy
    this.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
    this.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);

    // set the main window in the scroll pane
    this.setContent(content);
}

}

I then load the FXML, put the AnchorPane inside the Scrollpane, and let it show:

private final void initWindow() {
    try {
        // Load main window layout from fxml file.
        URL mainWindowURL = MainApp.class.getResource("view/MainWindow.fxml");
        FXMLLoader loader = new FXMLLoader(mainWindowURL, guiLabels);
        mainWindow = (AnchorPane) loader.load();
        MainWindowController controller = loader.getController();
        controller.setMainAppAndGUILabels(this);

        // create a scrollable Pane, and put everything inside
        scrollableMainFrame = new ScrollableMainFrame(mainWindow);

        // Show the scene containing the layout.
        Scene scene = new Scene(scrollableMainFrame);
        primaryStage.setScene(scene);            
        primaryStage.show();
    } catch (IOException e) {
        LOG.error("Error loading GUI!", e);
    }
}

So far so good, window shows up and has no scrollbars until I do not shrink it. But I'd like to maximize my window, as it has no sense to make it larger (the AnchorPane has a fixed size), only smaller. I have already figured it out, that one must set the Max size of the PrimaryStage to limit the actual window, limiting the ScrollPane has no effect.

And here is the problem: If I want to set a MaxHeight and MaxWidth for the PrimayStage, I only get unwanted results. If I want my PrimaryStage to have the same max size as the Anchorpane, the window either don't show up, or has scroll bars!

If I put this line in my InitWindow mehtod

        // Show the scene containing the layout.
        Scene scene = new Scene(scrollableMainFrame);
        primaryStage.setScene(scene);
        // set max window size
        primaryStage.setMaxHeight(scrollableMainFrame.getHeight());
        primaryStage.show();

nothing will appear, as apparently the 'scrollableMainFrame' has no hight at that point.

If I place the setMaxHeight() at the end, like

    primaryStage.setScene(scene);
    primaryStage.show();
    // set max window size
    primaryStage.setMaxHeight(scrollableMainFrame.getHeight());

then a max hight will be effectively set, but scroll bars appear and stay visible, even if the window has its full size!

Does anybody know why, and how could I set max sizes for my window, without scroll bars always on?

(Simply adding numbers to the max like primaryStage.setMaxHeight(scrollableMainFrame.getHeight() + 15); doesn't do anything at all, scroll bars still there!)

1
No time to test right now, but try primaryStage.setMaxHeight(primaryStage.getHeight()); after showing the stage. I think the problem you are running into is that setting the max height to the scrollpane's height doesn't allow room for the title bar, etc, so the window is always a little smaller than it should be. (You might need to experiment with this a bit to ensure the stage's height property is properly set before you call setMaxHeight(...).)James_D

1 Answers

1
votes

Thanks, James_D, you lead me to the solution!

It is indeed as you said, scrollbars appear, because the PrimaryStage also contains the title bar, which I forgot. This made me think: how can I calculate the full size of a window based on its content, to set it as a max size? Well, I don't need to! The logic is somewhat twisted, but works: I simply need to ask the Primarystage for its actual size, and set it as a maximum. The trick is, that I need to do that after the window has been created:

        // create the window
        primaryStage.show();
        // set actual size as max
        primaryStage.setMaxHeight(primaryStage.getHeight());
        primaryStage.setMaxWidth(primaryStage.getWidth());