1

I'm experiencing a problem with the layout after changing scenes is JavaFX when monitor scaling is set to 125%.

When scaling is set to 100% everything works fine.

I'm using JavaFX 11.0.2.

Here is my code:

import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class App extends Application {
    private Scene firstScene;
    private Scene secondScene;

    private Rectangle2D screenBounds = Screen.getPrimary().getBounds();
    private final int backButtonSize = (int) (screenBounds.getWidth() / 50);

    private Image image = new Image("https://imgur.com/download/uDlKu6Y");

    @Override
    public void start(Stage stage) {
        Button forwardButton = new Button("Forward");
        forwardButton.setOnAction(actionEvent -> stage.setScene(secondScene));
        firstScene = new Scene(new StackPane(forwardButton));

        Button backButton = new Button("Back");
        backButton.setOnAction(actionEvent -> stage.setScene(firstScene));
        backButton.setMinWidth(backButtonSize);
        ImageView imageView = new ImageView(image);
        imageView.setFitWidth(screenBounds.getWidth() - backButtonSize);
        imageView.setFitHeight(screenBounds.getHeight());
        imageView.setPreserveRatio(true);
        secondScene = new Scene(new BorderPane(imageView, null, null, null, backButton));

        stage.setX(screenBounds.getMinX());
        stage.setY(screenBounds.getMinY());
        stage.setWidth(screenBounds.getWidth());
        stage.setHeight(screenBounds.getHeight());
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setScene(firstScene);
        stage.show();
    }
}

The first scene that I set in stage (stage.setScene(firstScene) or stage.setScene(secondScene)) looks fine.

But after clicking on a button and changing scenes (calling event handlers from forwardButton.setOnAction(...) or backButton.setOnAction(...)), the layout is broken.

Normal first scene: Normal first scene

Normal second scene: Normal second scene

Broken first scene: Broken first scene

Broken second scene: Broken second scene

I would appreciate any help.

P.S. If anyone could suggest a way to make ImageView take the whole vertical space, I would also appreciate this.
But it is considered a much smaller problem right now.

Edit 1:

I've managed to fix the problem by changing panes, not scenes.
But I'm still wondering why the first attempt was unsuccessful.

Here is the updated code:

import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class App extends Application {
    private Scene scene;
    private Pane firstPane;
    private Pane secondPane;

    private Rectangle2D screenBounds = Screen.getPrimary().getBounds();
    private final int backButtonSize = (int) (screenBounds.getWidth() / 50);

    private Image image = new Image("https://imgur.com/download/uDlKu6Y");

    @Override
    public void start(Stage stage) {
        Button forwardButton = new Button("Forward");
        forwardButton.setOnAction(actionEvent -> scene.setRoot(secondPane));
        firstPane = new StackPane(forwardButton);

        Button backButton = new Button("Back");
        backButton.setOnAction(actionEvent -> scene.setRoot(firstPane));
        backButton.setMinWidth(backButtonSize);
        ImageView imageView = new ImageView(image);
        imageView.setFitWidth(screenBounds.getWidth() - backButtonSize);
        imageView.setFitHeight(screenBounds.getHeight());
        imageView.setPreserveRatio(true);
        secondPane = new BorderPane(imageView, null, null, null, backButton);

        scene = new Scene(firstPane);

        stage.setX(screenBounds.getMinX());
        stage.setY(screenBounds.getMinY());
        stage.setWidth(screenBounds.getWidth());
        stage.setHeight(screenBounds.getHeight());
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setScene(scene);
        stage.show();
    }
}
DfM
  • 529
  • 6
  • 19
  • 1. For full screen mode use `stage.setMaximized(true);`. 2. To make your code [mre] and usable by others use a web resource. See an example [here](https://stackoverflow.com/a/53927740/3992939) 3. How do you change the monitor scale ? – c0der Dec 09 '19 at 06:03
  • @c0der 1. If I use `setMaximized()` instead of `setX()`, `setY()`, `setWidth()` and `setHeight()`, I get some strange results (taskbar is displayed in the second scene and first scene gets really small) - see https://imgur.com/a/dWgOYgd. 2. Fixed. 3. It is set by OS (Windows in my case), I don't change anything on the Java side. – DfM Dec 09 '19 at 19:38

1 Answers1

0

To set your application to undercoated full screen use setFullScreen:

    //stage.setX(screenBounds.getMinX());
    //stage.setY(screenBounds.getMinY());
    //stage.setWidth(screenBounds.getWidth());
    //stage.setHeight(screenBounds.getHeight());
    //stage.initStyle(StageStyle.UNDECORATED);
    stage.setFullScreen(true);

To test it use the mre posted in the question.
In 125% scale it looks like:

enter image description here

enter image description here

c0der
  • 18,467
  • 6
  • 33
  • 65
  • That doesn't fix the first code version. I get some weird results: https://imgur.com/HTu8Ski. – DfM Dec 10 '19 at 22:40