High DPI Displays

与标准 DPI 显示器相比, 高 DPI 显示器具有更高的像素密度.

像素密度以每英寸点数 (DPI) 或每英寸像素 (PPI) 为单位, 由显示像素的数量及其大小决定. 因此, 仅凭像素数量不足以确定显示器是否属于高 DPI 类别.

4K 显示器具有固定数量的像素 (~8M), 但其 DPI 在 185 (23 英寸) 和 110 (40 英寸) 之间变化. 前者大约是标准 96 DPI 桌面分辨率的两倍: 后者几乎没有超过这个分辨率.

Challenges with High DPI

高 DPI 显示器给现有应用带来一些挑战:

  • 使用具有固定坐标的 UI 设计的应用程序看起来很小
    以点为单位指定字体大小和以像素为单位的其他大小的组合特别有问题, 因为点与显示器的分辨率无关. 例如, 假设文本 "hello" 周围有一个 40x20 像素的边框. 如果我们使用 12pt 字体, 它在低分辨率显示器上看起来会是正确的. 但是, 在高 DPI 显示器上, 边框会太小, 导致文本被剪裁.
  • 应用程序必须适应用户拥有多个分辨率不同的显示器的情况
    例如, 用户可能使用 4K 显示器作为图像编辑器的文档窗口, 但使用低分辨率显示器作为工具箱.

传统上, 为了支持高 DPI, Qt 会自动缩放字体, 并提供应用程序代码可用于缩放 UI 其余部分的 DPI 值.

High DPI Support on a System Level

Qt 支持高 DPI 模式, 其中主坐标系被虚拟化并独立于显示像素密度. 某些操作系统 (例如 macOS 和 iOS) 实现了此模式. 此外, 如果操作系统不支持此模式, Qt 还可以使用一个实现.

现在, 几何图形是在与设备无关的像素中指定的. 这包括 widget 和项目几何形状, 事件几何形状, 桌面, 窗口和屏幕几何形状, 以及动画速度. 输出以设备像素呈现, 这对应于显示分辨率. devicePixelRatio 是设备独立像素与设备像素坐标系之间的比率.

通常, 大多数应用程序都使用与设备无关的像素; 除了 OpenGL 和光栅图形代码之外.

Operating System Support

Qt 支持的操作系统为高 DPI 显示器提供以下功能:

macOS and iOS

Apple 平台在操作系统中实现了缩放和坐标系统虚拟化. 通常情况下, 不需要特殊配置.

在 macOS 上, 通过 Info.plist 文件中的设置启用高 DPI 支持; 因此请确保这些设置存在.

 <key>NSPrincipalClass</key>
 <string>NSApplication</string>
 <key>NSHighResolutionCapable</key>
 <string>True</string>

较新版本的 qmake 将生成带有 NSPrincipalClass 的 Info.plist 文件; 这已经足够了, 因为默认情况下 NSHighResolutionCapable 为 true.

注意: macOS 和 iOS 都可能会应用进一步的虚拟化, 使得设备像素不再与显示像素 1:1 对应. 这种情况发生在 iPhone 6+ 和启用了 "显示缩放" 配置的 macOS 上.

Microsoft Windows

Scaling

用户从控制面板或通过上下文菜单选择缩放系数. 这是通过使查询系统指标的函数返回不同的标准字体大小, 窗口边框大小等值来实现的. 它不执行任何实际的缩放.

DPI Awareness

Windows 上的应用程序可以采用以下 "DPI Awareness" 级别之一:

DPI Awareness LevelMeaning
DPI Unaware 这一级别是在 Windows Vista 中引入的. 对于应用程序, Windows 假装它在 1920x1080 的 96 DPI 标准显示器上运行, 并相应地缩放应用程序. 它旨在适应为低 DPI 显示器设计的旧应用程序. 这种类型的缩放可能会导致一些残影。.
System-DPI Aware这一级别是在 Windows Vista 中引入的. 仅当连接多个显示器时, 它与 Per-Monitor DPI Aware 不同. Windows 会计算适合所有连接的显示器的缩放比例.
Per-Monitor DPI Aware这一级别是在 Windows 8.1 中引入的. Windows 根本不执行任何缩放.

默认情况下, Qt 应用程序在 Windows 8.1 上设置为 Per-Monitor DPI Aware, 在 Windows 8 之前版本上设置为 System-DPI Aware. 从 Qt 5.4 开始, 可以通过平台插件的参数指定此级别:

 <application> -platform windows:dpiawareness=0,1,2

详见 Using qt.conf.

High DPI Support in Qt

Qt 提供了以下方法来处理应用程序中的高 DPI 支持.

  • 这种能力能够提供高分辨率的图像. 详见 Drawing High Resolution Versions of Pixmaps and Images.
  • Qt 5.6 支持遗留应用程序跨平台高 DPI 缩放, 与 macOS 的原生缩放类似. 这使得为低 DPI 屏幕编写的应用程序无需更改即可在高 DPI 设备上运行. 这项功能是可选的, 使用下列环境变量启用:
    • QT_AUTO_SCREEN_SCALE_FACTOR [boolean] 根据显示器的像素密度启用自动缩放. 这不会改变点大小字体的大小, 因为点是物理测量单位. 多个屏幕可能具有不同的比例因子.
    • QT_SCALE_FACTOR [numeric] 定义整个应用程序的全局比例因子, 包括点大小的字体.
    • QT_SCREEN_SCALE_FACTORS [list] 指定每个屏幕的比例因子. 这不会改变点大小字体的大小. 环境变量主要用于调试, 或解决具有错误 EDID 信息(扩展显示识别数据).

      格式可以是分号分隔的比例因子列表, 顺序与 QGuiApplication::screens() 相同, 或以分号分隔的 name=value 列表, 其中, nameQScreen::name() 相同.

    虽然 macOS 样式完全支持高 DPI, 但 Windows 桌面样式目前在某些比例因子方面存在一些限制. 在这些情况下, 考虑改用 Fusion 样式, 它在所有情况下都支持高 DPI.

    注意: 非整数比例因子可能会导致严重的缩放/绘画残影.

  • Qt::AA_EnableHighDpiScaling 应用程序属性 (在 Qt 5.6 中引入) 支持根据显示器的像素密度自动缩放.
  • Qt::AA_DisableHighDpiScaling 应用程序属性 (在 Qt 5.6 中引入) 可关闭所有缩放. 这适用于需要实际窗口系统坐标的应用程序, 无论环境变量如何. 该属性优先于 Qt::AA_EnableHighDpiScaling.
  • QT_ENABLE_HIGHDPI_SCALING 环境变量 (在 Qt 5.14 中引入) 可以根据显示器的像素密度进行自动缩放, 替换 QT_AUTO_SCREEN_SCALE_FACTOR.
  • QT_SCALE_FACTOR_ROUNDING_POLICY 环境变量 (在 Qt 5.14 中引入) 和 QGuiApplication::highDpiScaleFactorRoundingPolicy API 可以控制是否以及如何将设备像素比率舍入到最接近的整数. 这与 Windows 150% 缩放配置相关. 可能的值是 Round, Ceil, Floor, RoundPreferFloor, PassThrough. 详见 Qt::HighDpiScaleFactorRoundingPolicy.
  • 在 Qt 5.4 中, 通过 QT_DEVICE_PIXEL_RATIO 环境变量引入了高 DPI 缩放的实验性实现, 你可以将其设置为数字缩放因子或自动. 该变量在 Qt 5.6 中已弃用.

Migrate Existing Applications

要让专为低 DPI 值设计的应用程序在高分辨率显示器上快速运行, 请考虑以下方法之一:

  • 让应用程序在 Windows 上以 DPI Unaware 模式运行
  • QT_AUTO_SCREEN_SCALE_FACTOR 环境变量设为 1.

然而, 这些选项可能会导致一些缩放或绘图残影.

从长远来看, 应用程序应该适合在不修改的情况下运行:

  • 始终使用 QPainter 绘图 API 的 qreal 版本.
  • 根据相应的屏幕尺寸调整窗口和对话框的尺寸.
  • 将布局和绘图代码中的硬编码尺寸替换为根据字体规格或屏幕尺寸计算得出的值.

Glossary Of High DPI Terms

TermDefinition
Device Independent Pixels应用程序使用的像素 (用户空间), 受操作系统或 Qt 的缩放影响.
Device Pixels显示设备的像素.
Device Pixel Ratio操作系统或 Qt 应用的比例因子.
Logical DPI用于将以点为单位定义的字体大小转换为以像素为单位的字体大小的分辨率. 标准值为 96, 128, ... 192.
Physical DPI通过显示器的尺寸除以像素数获得的物理分辨率.
User Space应用程序在设备独立像素中使用的坐标空间.