跳到主要内容

JEP 263:Windows 和 Linux 上的 HiDPI 图形

概括

在 Windows 和 Linux 上实现 HiDPI 图形。

动机

开发人员和用户对在 HiDPI 显示器上运行的应用程序有一些基本期望:

  • Windows 和 GUI 组件应根据平台建议具有适当的大小,

  • 尽管 HiDPI 设置指示任何默认缩放,文本仍应保持清晰,并且

  • 图标和图像应该平滑,并且最好具有适合显示器像素密度的细节。

不幸的是,Java 应用程序的大小和渲染仍然基于 Windows 和 Linux 上的像素,甚至在像素密度是传统显示器 2 到 3 倍的 HiDPI 显示器上也是如此。这导致 GUI 组件和窗口小了 2 到 3 倍,因此太小而无法阅读或有效交互。

JDK 已经支持 Mac OS X 上的 HiDPI“视网膜显示器”,并以适合显示器密度的尺寸显示清晰的文本和图像。 Mac“视网膜”支持已经为在所有平台上支持 HiDPI 显示器提供了相当多的基础工作,但是应用程序在不同平台上处理 HiDPI 的方式存在差异,这意味着还需要进行额外的工作来概括已完成的工作对于Mac。

现在应该为 Windows 和 Linux 平台提供相同的自动缩放和大小调整。

描述

Windows 上的 HiDPI

Windows 控制面板为用户提供了多种方法来请求在多个版本中缩放桌面上的组件和窗口(自 Windows XP 以来就以各种形式)。某些操作系统版本还提供了自动缩放未声明为“DPI 感知”的应用程序的功能。 “DPI 不感知”应用程序的默认缩放可能会导致许多视觉伪影,包括模糊的窗口、不准确的布局和剪切的文本,因此 Java 运行时已声明自己“DPI 感知”一段时间以避免模糊和布局问题。不过,支持根据 DPI 缩放内容并不是一项简单的任务,并且由于大多数显示密度只需要 25% 的小缩放,因此决定忽略建议的缩放准则和策略,并继续呈现 AWT 和 Swing 组件1:1 像素缩放,让 JDK 应用程序比标准稍小,但文本和图形清晰。

不过,最近显示器的像素密度有了很大的提高,很容易找到笔记本电脑的屏幕密度是做出这些决定时常见显示器密度的 2 到 3 倍。因此,这些较新的 Windows 机器上的 Java 应用程序有时会小到无法使用——这不再是“窗口稍小 vs 模糊”的情况,因此我们需要正确缩放应用程序窗口。

Windows API 提供了编写 DPI 感知应用程序的指标、机制和指南,使 UI 在各种 DPI 显示设置中看起来保持一致,并响应用户首选项,使 UI 足够大,以便用户能够舒适地与 UI 组件交互。

Windows Direct2D 图形 API 自动遵循系统 DPI,以 DIP(与设备无关的像素)表示坐标,使位图具有 DPI,并通过考虑 DPI 来正确缩放它们。但是,AWT 和 Swing 库并不基于 Direct2D 图形 API。

Windows 7 及更高版本提供了多种获取桌面水平和垂直 DPI 的方法,包括方法GetDesktopDpi以及最近在 Windows 8.1 中提供的GetDpiForMonitor方法和WM_DPICHANGED消息。这些值可用于缩放窗口大小、鼠标坐标和字体,以支持 AWT/Swing 库中的 HiDPI。 Java2D 渲染层中已经存在对缩放的必要支持,但我们需要将这些值通告给 Swing 和 AWT,并更新它们的组件以识别和遵循缩放因子。此支持包括确保向 Java2D 对象提供所需的渲染比例因子Graphics,使用目标的适当比例因子渲染中间渲染图像,以及需要重新检查有关渲染调用中的坐标如何映射到像素的任何假设。

Linux 上的 HiDPI

GTK+ 3 库中已实现 HiDPI 支持。当使用 HiDPI 显示器时,GTK 库会自动缩放客户端的应用程序。

Java2D和AWT使用XLib库,不支持HiDPI。因此,当前的 Java 应用程序在 Linux 上的 HiDPI 显示器上看起来小了 2 到 3 倍。

此外,任何使用 GTK 外观风格的 Java 应用程序都可以自动受益于 GTK 库中 HiDPI 的支持,而窗口和其他组件的大小可以与已放大 2-3 倍的 GTK 组件匹配,以满足 HiDPI 要求。这可能会导致JDK-8058742中描述的问题。

备择方案

当在 HiDPI 显示器上运行时,开发人员可以手动缩放应用程序中的所有 GUI 元素,但这需要对应用程序进行大量重构工作,并且 Swing 和 AWT 组件的编写方式无法与从外部缩放它们的尝试很好地配合。

测试

应在 HiDPI 显示器上进行以下测试。最好有多种屏幕比例 - 192 DPI 和 144 DPI 将是一个很好的最小支持矩阵。请注意,可以使用 Windows 控制面板将非常高的 DPI 显示器设置为较低的人工 DPI,因此不一定需要其他系统,但必须在测试运行之间重新配置它们。此外,在 Windows 上更改 DPI 通常需要重新启动才能将新的 DPI 通告给应用程序。

在 Windows 中,可以在控制面板中设置 DPI 设置。 Windows 7、Windows 8.1 和旧版本的 Windows 上存在不同的控制面板和允许的设置,但所有这些都倾向于将相同类型的信息传递到应用程序(X 和 Y 的指示 DPI) ,所以此时在控制面板的变化下不需要进行额外的测试,这只是一个影响测试环境如何配置的细节。

在 Linux 上,可以使用 GTK+ 3 的 GDK_SCALE 环境变量或 GNOME 3 的缩放因子设置来模拟 DPI 设置。

应检查以下项目:

  • 文字不应模糊
  • 组件(标签和按钮)中的文本不应被剪切
  • UI 组件布局应在 AWT/Swing 上保持合理(即没有重叠或奇怪的间隙)
  • 当应用程序或测试用例提供时,应在 AWT/Swing 对话框和组件上使用高分辨率图标
  • 应用程序应正确处理鼠标事件
  • 应用程序的大小应与表现良好的 DPI 感知本机应用程序相似