如何从 Java 代码中找到真实的显示密度 (DPI)?
How to find real display density (DPI) from Java code?
我打算做一些低级渲染的东西,但我需要知道真实的显示 DPI 才能使所有内容都具有正确的尺寸。
我找到了一种方法:
java.awt.Toolkit.getDefaultToolkit().getScreenResolution()
— 但它 returns 在 OS X 和 "retina" 显示器上的不正确结果,它是实际 DPI 的 1/2。 (在我的情况下它应该是 220,但它是 110)
所以要么其他一些更正确的 API 必须可用,要么我需要为 OS X 实施 hack — 以某种方式确定当前显示是否为 "retina" .但我也找不到任何方法来查询这些信息。有 this answer 但在我的机器上 Toolkit.getDefaultToolkit().getDesktopProperty("apple.awt.contentScaleFactor")
只是 returns null.
我该怎么做?
看起来目前可以从 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;
}
这是一个来自@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;
}
我打算做一些低级渲染的东西,但我需要知道真实的显示 DPI 才能使所有内容都具有正确的尺寸。
我找到了一种方法:
java.awt.Toolkit.getDefaultToolkit().getScreenResolution()
— 但它 returns 在 OS X 和 "retina" 显示器上的不正确结果,它是实际 DPI 的 1/2。 (在我的情况下它应该是 220,但它是 110)
所以要么其他一些更正确的 API 必须可用,要么我需要为 OS X 实施 hack — 以某种方式确定当前显示是否为 "retina" .但我也找不到任何方法来查询这些信息。有 this answer 但在我的机器上 Toolkit.getDefaultToolkit().getDesktopProperty("apple.awt.contentScaleFactor")
只是 returns null.
我该怎么做?
看起来目前可以从 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;
}
这是一个来自@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;
}