高DPI#

描述了Qt对高DPI显示器的支持。

高DPI显示器(也称为视网膜显示器)具有与其物理尺寸(mm)相比高分辨率(像素),从而产生高像素密度,或称为高位每英寸(DPI)。增加的分辨率用于在屏幕上提供更详细的内容(更平滑的文本,更详细的图标),而不是更多的内容(更多窗口,更大的窗口尺寸)。

Qt支持所有平台上的高DPI显示器,并提供了一个统一的API,它可以抽象出平台差异。Qt将自动考虑在使用Qt Widgets和Qt Quick等高级API时显示器的分辨率,并且应用程序只需要提供高分辨率资源,例如图像和图标。平台用户首选项的变化将自动被检测到。

较低的图形绘制级别(例如OpenGL代码)需要意识到高DPI,但可以使用跨平台Qt API来了解平台的显示分辨率。

概念模型#

Qt使用一种模型,其中应用程序坐标系独立于显示设备的分辨率。应用程序在设备无关像素上操作,然后这些像素通过一个称为设备像素比例的缩放因子映射到显示器的物理像素。这个缩放因子以浮点数表示,例如1.02.0,或者非正式地表示为1x2x

例如,创建一个QWindow或QWidget,并将其大小设置为200x200,将在标准密度显示器(具有设备像素比例为1.0)上覆盖200x200个显示像素,但在高密度显示器(具有设备像素比例为2.0)上覆盖400x400个像素。

该模型适用于更高层级的Qt GUI、Widgets和Quick API中的大多数单位,包括小部件和项的几何形状、事件几何形状、桌面、窗口和屏幕几何形状,以及动画速度。

注意

该模型不考虑UI类之间的差异,例如触摸目标与鼠标目标的大小。

绘图#

Qt将自动利用高DPI显示的高密度,当使用Painter之类的绘图API,或当在Qt Quick中渲染图形原语或文本时。

因此,应用程序可以在单个统一坐标系中操作,而不需要考虑应用程序可能运行的显示器的显示密度。

然而,当使用低级绘图API,例如OpenGL时,应用程序需要考虑显示器的设备像素比例。这在每个窗口中都可以通过QWindow::devicePixelRatio()(跟踪窗口在不同显示器之间移动时的设备像素比例)或通过每个显示器,例如QScreen::devicePixelRatio()来获得。

图像缓冲区,如QImage和QPixmap,表示原始像素,因此不使用之前所述的设备无关坐标系统进行操作。一个大小为400x400的QImage,其设备像素比为2.0,将适合高密度(2x)显示上的200x200 QWindow,或者如果针对正常密度(1x)显示,则将在绘制时自动缩放到200x200。有关更多详细信息,请参阅“绘制高分辨率图像和位图的版本”。

图像资源#

为了利用高DPI显示增加的像素密度,应用程序还应包含静态图像资源的高DPI版本。这是通过使用高密度资源特殊命名约定实现的,例如 [email protected],并将普通密度图像和高密度图像都加载到QIcon中。Qt将在运行时自动为目标显示选择最佳表示。有关更多详细信息,请参阅“高DPI图标”。

设备无关屏幕几何图形#

Qt应用程序通常在设备无关像素上运行。这包括报告给应用程序的窗口和屏幕几何图形。

这意味着QScreen::geometry()可能不会返回屏幕的物理像素计数或操作系统报告的像素大小。这会影响虚拟桌面几何形状。

现代桌面操作系统通常为所有连接的屏幕创建一个共享坐标系统,并允许用户将屏幕放置在物理屏幕设置中匹配,通常通过配置对话框完成。如果在这种等效于Qt的设备无关像素的坐标系统中进行此定位(如macOS上),则QScreen几何形状将与原生屏幕布局匹配。如果在屏幕物理像素中定位(如Windows上),则Qt处理屏幕几何形状可能会在虚拟桌面几何形状中引入不用于任何屏幕的“间隙”。

具体来说,Qt将调整屏幕大小(产生一个“较小”的屏幕,对于正缩放因子),但不会更改屏幕位置。这将产生一种类型为“岛屿屏幕”的虚拟桌面几何形状。

应用程序代码不应假设一个屏幕紧邻外部的一个屏幕的位置是一个在相邻屏幕上的有效位置。相反,使用QGuiApplication::screens()获取屏幕列表,并使用此列表来推理可用屏幕几何形状。

配置#

作为最终用户,您可能想调整DPI或缩放设置以匹配显示硬件,或者考虑到观看距离和个人偏好。这些调整应使用平台的原生显示设置完成,以便所有应用程序都会同意相同的DPI或缩放因子值。Qt不提供供最终用户配置Qt高DPI支持的设施。

操作系统可以将缩放因子表示为基数(例如1.5),百分比(150%)或每英寸点(144 DPI)。Qt将这些转换为应用程序看到的设备像素比。在后一种情况下,Qt假定一个“基”DPI(例如,X11上的96),并相应地计算结果设备像素比。

整数缩放因子(例如1.0或2.0)是首选的,可获得最佳结果。“四舍五入”缩放因子到25%的增量也可以给出良好的结果。将缩放因子或DPI设置为确切的物理显示DPI可能由于涉及分数缩放而不产生良好的视觉效果。如果在这种情况下应用程序在视觉上受到影响,则可以使用QGuiApplication::setHighDpiScaleFactorRoundingPolicy()来限制它将看到的缩放因子。

平台细节#

以下表格描述了如何在各种平台上配置高DPI。

平台

配置

macOS

在显示首选项中为每个显示器设置缩放比例。macOS会将此作为整数设备像素比反映给Qt。

Windows

在显示设置中为每个显示器设置缩放比例。基本缩放比例是100%,可以以25%的步长进行调整。

Ubuntu

在显示设置中设置缩放比例。在Ubuntu 20.04及以后的版本中,可以按显示器进行设置,以25%为增量。旧版本支持设置为全局缩放100%或200%。

X11

设置Xft.dpi,或者选择使用物理DPI。查阅下面的“配置X11”。

Wayland

Qt读取wl_output::scale,该值限于整数。Wayland合成器通常有一个设置缩放比例的配置选项,例如weston --scale

EGLFS

QT_FONT_DPI设置为所需的逻辑DPI值,例如QT_FONT_DPI=192。Qt假设基础DPI为96,并据此缩放UI。

注意

一些窗口管理系统可能有局限性,这些局限性在Qt中也有体现。Qt不提供针对这些局限性的解决方案。相反,可以考虑在窗口管理系统级别上解决这些问题。

配置X11#

Qt所需的配置输入为每个屏幕的逻辑DPI。目前,X11提供全局逻辑DPI或每个屏幕的物理DPI。这两个都不是Qt所需的,这使得X11上的DPI配置比其他平台更复杂。

桌面环境,如Ubuntu和Kubntu,实现了针对逻辑DPI缺失的解决方案,并提供了易于配置的高DPI支持。如果您希望手动配置X11 DPI设置,则本节描述了Qt读取哪些X11设置。

某些X11配置工作流程可能涉及覆盖屏幕的报表物理尺寸,以便DPI计算得出特定的DPI值。Qt支持此工作流程,但需要选择启用,如下文所述。

确切的配置优先级如下,Qt将使用第一个可用选项。请注意,行为取决于使用的Qt版本。Qt 5的行为假设AA_EnableHighDpiScaling已设置(此标志在Qt 6中不需要)。

+———————————+——————————————————————————————————————————————————————————————————————————————————————————————++ |X11 DPI配置优先级 | +=================================+==========================================================================================================================================================================================================================================================================================++ |属性 |注释 || +———————————+——————————————————————————————————————————————————————————————————————————————————————————————++ |1. Xft/DPI |来自X设置。全局逻辑DPI值。 || +———————————+——————————————————————————————————————————————————————————————————————————————————————————————++ |2. Xft.dpi |来自X资源。全局逻辑DPI值。 || +———————————+——————————————————————————————————————————————————————————————————————————————————————————————++ |3. RandR物理DPI [仅Qt 5]|从“randr”提供的每个屏幕的物理尺寸和像素尺寸计算得出的DPI。具体来说,使用“xcb_randr_screen_change_notify_event_t”结构的“mwidth”和“mheight”字段。DPI将四舍五入到整数并夹在至少96之间。|| +———————————+——————————————————————————————————————————————————————————————————————————————————————————————++ |4. 96 DPI |回退值。 || +———————————+——————————————————————————————————————————————————————————————————————————————————————————————++

QT_USE_PHYSICAL_DPI覆盖

设置QT_USE_PHYSICAL_DPI=1使Qt无条件使用RandR物理DPI;具体来说,使用xcb_randr_screen_change_notify_event_t结构的mwidth和mheight字段,DPI值将四舍五入到整数。

配置Windows#

Qt自动使用Windows显示缩放设置;无需特定设置。例如,如果显示设置为175%缩放,则Qt应用程序将在此屏幕上看到一个设备像素比为1.75。

Windows定义了几个DPI感知级别,应用程序可以通过设置这些级别来选择性地启用高DPI功能。默认情况下,Qt 6是按显示器DPI感知V2。如果您正在集成假设单一全局DPI的代码,则可能需要设置不同的感知级别。这可以通过向qt.conf添加条目来完成

[Platforms]
WindowsArguments = dpiawareness=0,1,2

测试#

QT_SCALE_FACTOR#

设置QT_SCALE_FACTOR环境变量以提供应用程序的全局缩放因子。

QT_SCALE_FACTOR=2 ./myapp

这将按给定因子缩放所有应用程序几何形状(包括设备像素比),从而独立于可用硬件测试对高DPI的支持。设置的缩放因子将按原样由Qt使用,并且不受舍入策略的影响。

由QWindow::devicePixelRatio()返回的有效设备像素比将是设置的缩放因子和原生设备像素比的乘积。例如,在2x Wayland显示器上设置QT_SCALE_FACTOR=2将导致应用程序看到一个设备像素比为4。

DprGadget#

DprGadget测试应用程序可以用于检查原生配置以及Qt如何对它做出反应

../_images/dprgadget.png

DprGadget显示窗口的设备像素比,如QWindow::devicePixelRatio()报告的。此外,它还显示窗口所在的屏幕的原生DPI和设备像素比,由QPlatformScreen::logicalDpi()和QPlatformScreen::devicePixelRatio()报告。

显示的值应在屏幕上自动更新,并随DPI变化而变化;对话框应保持相同的尺寸。如果不是这样,那么这可能是Qt的一个错误。

DprGradget是Qt手动测试套件的一部分,可以在qtbase/tests/manual/highdpi/dprgadget找到。

环境变量参考#

本节列出了Qt识别的与高DPI相关的环境变量。按字母顺序排列

  • QT_ENABLE_HIGHDPI_SCALING 将0设置为禁用高DPI缩放;有效地回退到Qt 5默认行为。请注意,这对Wayland或macOS等平台没有影响——它不会禁用任何原生高DPI支持。此变量仅用于测试目的,我们不建议永久设置此变量。

  • QT_FONT_DPI 设置全局DPI。这是一个为向后兼容性提供的保留环境变量。

  • QT_SCALE_FACTOR 设置全局缩放因子。用于调试和测试目的。

  • QT_SCALE_FACTOR_ROUNDING_POLICY 设置缩放因子舍入策略,该策略应用于从屏幕DPI计算出的缩放因子。支持值包括

    • Round(Qt 5默认值)

    • PassThrough(Qt 6默认值)

  • QT_SCREEN_SCALE_FACTORS 设置一系列屏幕缩放因子。该列表可以是两种格式之一;一个分号分隔的屏幕缩放因子列表(“1;1.5;2”)或一个分号分隔的screen=factor条目列表(“screenA=1;screenB=1.5;screenC=2”)。不推荐设置此环境变量,因为它阻止Qt使用系统DPI值。

  • QT_USE_PHYSICAL_DPI 使Qt使用物理DPI而不是逻辑DPI。通常使用逻辑DPI是最好的选择;当逻辑DPI不可用且知道物理DPI是正确的时,可以设置此环境变量。

坐标系参考#

  • 设备无关像素 这是 Qt 的主坐标系。窗口、小部件、Quick 项目、事件和屏幕几何形状都使用设备无关像素。通常,设备无关像素在各种设备和屏幕密度下具有恒定的可视大小。尽管这是一个概括,但确切大小取决于设备配置。

  • 设备像素 这种坐标系用于光栅化和底层图形任务,例如在使用 OpenGL API 的情况下。设备像素坐标系通常等同于显示的物理坐标系,但这并不保证。例如,macOS 和 Ubuntu 可能会根据显示设置应用额外的缩放。

  • 本地像素 这是由本地 API(如 Win32 或 Cocoa [macOS])使用的坐标系。根据平台和屏幕配置,本地像素可能与设备无关像素或设备像素等效。