如何从Java代码中找到实际显示密度(DPI)?

时间:2016-11-03 10:52:08

标签: java macos retina-display dpi hidpi

我要做一些低级渲染的东西,但我需要知道真正的显示DPI才能制作出正确尺寸的东西。

我找到了一种方法: java.awt.Toolkit.getDefaultToolkit().getScreenResolution() - 但它在OS X上返回不正确的结果,显示“视网膜”,它是实际DPI的1/2。 (在我的情况下它应该是220,但它是110)

因此,要么其他一些更正确的API必须可用,或者我需要为OS X实现一个hack - 以某种方式查找当前显示是否为“retina”。但我找不到任何方法来查询这些信息。有this answer,但在我的机器Toolkit.getDefaultToolkit().getDesktopProperty("apple.awt.contentScaleFactor")上只返回null。

我该怎么做?

2 个答案:

答案 0 :(得分:3)

看起来目前可以从java.awt.GraphicsEnvironment获取它。这是注释的代码示例,它适用于最新的JDK(8u112)。

// find the display device of interest
final GraphicsDevice defaultScreenDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

// on OS X, it would be CGraphicsDevice
if (defaultScreenDevice instanceof CGraphicsDevice) {
    final CGraphicsDevice device = (CGraphicsDevice) defaultScreenDevice;

    // this is the missing correction factor, it's equal to 2 on HiDPI a.k.a. Retina displays
    final int scaleFactor = device.getScaleFactor();

    // now we can compute the real DPI of the screen
    final double realDPI = scaleFactor * (device.getXResolution() + device.getYResolution()) / 2;
}

答案 1 :(得分:1)

这是@ sarge-borsch采纳的示例,不会在Windows和Linux上引发编译错误。

public static int getScaleFactor() {
    try {
        // Use reflection to avoid compile errors on non-macOS environments
        Object screen = Class.forName("sun.awt.CGraphicsDevice").cast(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice());
        Method getScaleFactor = screen.getClass().getDeclaredMethod("getScaleFactor");
        Object obj = getScaleFactor.invoke(screen);
        if (obj instanceof Integer) {
            return ((Integer)obj).intValue();
        }
    } catch (Exception e) {
        System.out.println("Unable to determine screen scale factor.  Defaulting to 1.");
    }
    return 1;
}
相关问题