JavaFX: supporting different resolutions

Viewed 2264

I'm trying to understand how to support different resolutions in JavaFX. I'm looking for a sort of a guide about how to achieve this.

I want to create an application which requires a minimum resolution of, for example, 1280×720. And I want that my applications looks fine on any higher resolution too (like 1920×1080). Also, the application should look good at different DPI values. How can I do that?

Lets set as minimum requirements JDK 11.0.2+ and JavaFX 11.0.2+ to be more specific.

What I (seem to) understand now:

  1. Minimum width and height of the stage have to be set.
  2. I can not bother about DPI support, as it seems to be implemented.

What I still don't understand:

  1. How do I set the dimensions of elements, indents, etc.
    • Should I set values in pixels for the minimum supported resolution and then multiply them by the coefficient according to the current resolution?
    • Or should I build up the size as a percentage of the width/height of the screen?
    • Or should I do it all in a very different way?
  2. Should I avoid any controls/layouts?

I hope I was clear enough.

I'm new to creating interfaces for real, not toy applications. And I will appreciate any help, be it comments, explanations, code samples or links to articles.

Thank you in advance for your help.

4 Answers

Well that a very good question as JavaFX doesn't support responsive resolution on the fly so you gonna do it by yourself

  1. First try to rely on the different layouts to distribute the UI components according to the computed location, width and height like in BorderPane that have 5 sections to set your components at effortlessly
  2. After doing the first step and you still have some components that want custom modification in terms of width and height set your desirable width and height and multiply these values by a ratio this ratio you can calculate it by getting the screen resolution so the next time you run the app on a different screen with different resolution it's gonna give a different width or height for that component
  3. You can also provide a different FXML file for each supported resolution by your app so you can run the appropriate design and also for landscape and portrait cases
  4. Of course you can look for a third party library that can provide responsive component like BootstrapFX which is similar to that for web design and also there is ResponsiveFX too but I didn't try them before

I hope my answer help you or put you on the right track to make some cool apps

Every component (button, text field, etc.) calculates its own preferred size, based on resolution, font sizes, the theme chosen by the user, and so on. All you have to do is make sure you don’t interfere with that. So don’t set any dimensions.

When you place components in a layout (any subclass of Pane other than AnchorPane), the layout will do its best to respect each child’s preferred size. In most applications, you will never have to set a single width or height explicitly.

Hi try to use different fxml-Files:

MaximizedPane.fxml: --> see prefWidth / perfHight

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.Label?>
<?import javafx.stage.Screen?>

<StackPane xmlns:fx="http://javafx.com/fxml/1"
           prefWidth="${screen.visualBounds.width}" 
           prefHeight="${screen.visualBounds.height}" >
    <fx:define>
        <Screen fx:factory="getPrimary" fx:id="screen"/>
    </fx:define>
    <Label text="A maximized pane"/>    
</StackPane>

Load the fxml-files dynamicly:

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class MaximizedFXMLPane extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {
        Scene scene = new Scene(FXMLLoader.load(getClass().getResource("MaximizedPane.fxml")));
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

Example from my git archive: https://github.com/src-mgra/my-calendar/blob/master/MyCalendar/src/sample/Main.java


Another way is to use scenes:

import java.awt.Dimension;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class ScreenResolutionDemo extends Application {


    @Override
    public void start(Stage primaryStage) throws Exception {
        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        double width = screenSize.getWidth() / 3;
        double height = screenSize.getHeight() / 2;

        try {
            **primaryStage.setScene**(new Scene(new AnchorPane(), *width*, **height**));
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

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

}

I am currently building a desktop application with pretty much the same constraints. I faced this question a month ago but later on found out that I need not do anything. The Pane will automatically resize the internal elements as per the screen resolution. As correctly mentioned by VGR that Anchorpane will not do this resizing of child elements and I need to replace all Anchorpane with Pane.

Another issue was faced at one of the test machine that the stage were being displayed too large for the low resolution display and wasn't being resized automatically. To resolve this, I set the resolution of the screen to another value and then switched it back to the original value and it got fixed.

You will need to set the minimum and(or) maximum size of the stage and(maybe) set it non-resizable and that must work.

Related