2

How can I reliably find out whether my JavaFX program is running on a retina device and what pixel scaling ratio is used. Calling something like

System.out.println(Screen.getPrimary().getDpi());

just returns 110 on my Mac. This is exactly half of the actual physical dpis so the information provided by the Screen class is quite useless.

Is there any other way to find out what I am looking for?

Michael

mipa
  • 10,369
  • 2
  • 16
  • 35

1 Answers1

2

I think I can now answer my own question. Officially there does not seem to be any way to find out what the physical DPIs of your screen are. The only way seems to be to use some private API like in the following example:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Screen;
import javafx.stage.Stage;

public class PixelScaleTest extends Application {

    public static double getPixelScale(Screen screen) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Method m = Screen.class.getDeclaredMethod("getScale");
        m.setAccessible(true);
        return ((Float) m.invoke(screen)).doubleValue();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        try {
            System.out.println("PixelScale: " + getPixelScale(Screen.getPrimary()));
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            e.printStackTrace();
        }
        Platform.exit();
    }

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

}

With the pixel scale factor you can compute your physical DPIs. On a standard Screen this factor should be 1.0 and on a Mac Retina it should be 2.0.

mipa
  • 10,369
  • 2
  • 16
  • 35
  • Starting JavaFX 9, please make use of either [getOutputScaleX()](https://docs.oracle.com/javase/9/docs/api/javafx/stage/Screen.html#getOutputScaleX--) or [getOutputScaleY()](https://docs.oracle.com/javase/9/docs/api/javafx/stage/Screen.html#getOutputScaleY--) methods on Screen. – ItachiUchiha Aug 21 '18 at 11:33
  • @ItachiUchiha Yes, I know but thanks for pointing this out here. Starting with JavaFX 9 there is new public API which makes this question and answer obsolete. – mipa Aug 21 '18 at 11:38
  • I don't think the question is obsolete. Moreover, the factor still remains 2, so the answer is partially valid as well. You may want to update your answer with JavaFX 9 alternatives ;) – ItachiUchiha Aug 22 '18 at 03:31
  • This doesn't work on Java 8 on my Mac. I get `java.lang.NoSuchMethodException: javafx.stage.Screen.getScale()` – whoKnows Jul 21 '20 at 17:09
  • Who still cares for Java 8 these days when writing JavaFX apps? – mipa Jul 21 '20 at 19:44