3. 屏幕与显示基础

在 Qt Quick 多屏与高分辨率适配中,最容易混淆的不是 API,而是一组看似相近的显示术语。物理分辨率、逻辑分辨率、DPI、PPI、缩放因子、设备像素比,它们分别描述“硬件有多少像素”“系统让程序看到多大坐标空间”“像素有多密”“系统把界面放大多少倍”等不同层面。只有先厘清这些概念之间的换算关系,才能理解为什么同一段 QML 在不同屏幕上尺寸不同、为什么截图会模糊、为什么鼠标坐标需要换算。

一、核心原理:从硬件像素到逻辑坐标

物理分辨率(Physical Resolution)指显示设备实际拥有的像素总数,例如 3840×2160,表示横向 3840 个物理像素、纵向 2160 个物理像素。它是硬件属性,不会因为系统缩放而改变。逻辑分辨率(Logical Resolution)则是操作系统或 Qt 呈现给应用程序的坐标空间大小,例如在 200% 缩放下,3840×2160 的屏幕可能对应 1920×1080 的逻辑坐标。逻辑分辨率决定了 QML 中 Screen.width、Screen.height 以及窗口坐标的数值范围。

PPI(Pixels Per Inch)表示每英寸包含多少物理像素,衡量的是“像素密度”,由物理分辨率和屏幕物理尺寸共同决定。DPI(Dots Per Inch)原本用于打印领域,表示每英寸可打印的点数;在显示领域常被借用来描述系统认为的像素密度,并进一步参与缩放策略。Qt 中常见的 Screen.pixelDensity 返回的是每毫米物理像素数,而 logicalDotsPerInch 则反映系统缩放后的逻辑 DPI。

缩放因子(Scale Factor)是逻辑坐标与物理像素之间的倍率。若缩放因子为 2,则 1 个逻辑像素对应 2×2=4 个物理像素。设备像素比(Device Pixel Ratio,DPR)通常与缩放因子同义或高度相关,表示一个逻辑像素对应多少个物理像素。在 Qt Quick 中,Screen.devicePixelRatio 就是这一比值。它直接影响图片资源选择、Canvas 绘制、ShaderEffect 以及自定义 OpenGL 渲染的清晰度。

显示术语关系:硬件像素 → 系统缩放 → 逻辑坐标 物理分辨率 3840 × 2160 物理像素 硬件属性,不随缩放改变 决定 PPI 的分子 缩放因子 / DPR scale = 2.0 1 逻辑像素 = 2×2 物理像素 Qt: Screen.devicePixelRatio 逻辑分辨率 1920 × 1080 逻辑坐标 QML 中 width/height 的范围 窗口与鼠标坐标空间 PPI 每英寸物理像素数 = √(宽² + 高²) / 屏幕对角线英寸 衡量像素密度,与缩放无关 DPI 系统逻辑密度参考值 logicalDotsPerInch 影响字体与控件默认大小 常见误区 把 DPI 当 PPI 使用 用物理像素写死尺寸 忽略 DPR 导致图片模糊 换算关系: 逻辑分辨率 = 物理分辨率 ÷ 缩放因子 | 物理像素 = 逻辑像素 × 设备像素比 | PPI 由物理分辨率与屏幕尺寸决定,DPI 由系统缩放策略决定

二、方法流程:在 Qt Quick 中读取与换算

Qt Quick 通过 Screen 附加类型暴露屏幕信息。典型读取方式如下:

import QtQuick
import QtQuick.Window

Window {
    visible: true
    width: 800
    height: 600

    Component.onCompleted: {
        console.log("物理分辨率:", Screen.width * Screen.devicePixelRatio,
                    "x", Screen.height * Screen.devicePixelRatio)
        console.log("逻辑分辨率:", Screen.width, "x", Screen.height)
        console.log("设备像素比:", Screen.devicePixelRatio)
        console.log("逻辑DPI:", Screen.logicalDotsPerInch)
        console.log("像素密度(每毫米):", Screen.pixelDensity)
    }
}

换算时牢记两条主线:第一,QML 中的 width、height、x、y 默认都是逻辑坐标;第二,真正落到屏幕上的物理像素等于逻辑值乘以 devicePixelRatio。因此,若要让一张图片在任何缩放下都清晰,应提供与物理像素匹配的高分辨率资源,或使用矢量图与 Image 的 sourceSize 控制解码尺寸。

三、案例场景:同一窗口在不同屏幕上的表现

假设有一台 27 英寸 4K 显示器,物理分辨率 3840×2160,系统缩放 200%。此时逻辑分辨率为 1920×1080,设备像素比为 2.0。一个 width: 400 的矩形,在逻辑坐标中占 400 单位,实际占用 800 个物理像素。若另一台 24 英寸 1080p 显示器缩放为 100%,逻辑分辨率就是 1920×1080,设备像素比为 1.0,同样 width: 400 的矩形只占 400 个物理像素。两者逻辑尺寸相同,但物理清晰度和实际视觉大小可能不同,这正是多屏适配需要处理的核心差异。

术语 含义 典型取值 是否随系统缩放变化
物理分辨率 硬件实际像素总数 3840×2160 否
逻辑分辨率 应用可见坐标空间 1920×1080 是
PPI 每英寸物理像素数 约 163 否
DPI 系统逻辑密度参考 96 / 144 / 192 是
缩放因子 逻辑到物理的倍率 1.0 / 1.5 / 2.0 是
设备像素比 1 逻辑像素对应物理像素数 1.0 / 2.0 / 3.0 是

四、误区与复盘

误区一:把 DPI 和 PPI 混为一谈。PPI 是硬件像素密度,DPI 是系统逻辑密度。一个 4K 手机屏幕 PPI 可能超过 500,但系统 DPI 可能被设定为 480 或 420,二者并不相等。

误区二:用物理像素写死 QML 尺寸。如果直接按 3840 设计界面,在 1080p 屏幕上会溢出;正确做法是以逻辑坐标设计,让缩放因子自动处理物理映射。

误区三:忽略设备像素比导致图片模糊。在 DPR=2 的屏幕上,一张 100×100 的位图若只提供 100×100 像素,会被拉伸到 200×200 物理像素,必然模糊。应提供 @2x 资源或使用 SVG。

复盘时可以用一句话串联:物理分辨率是“硬件有多少像素”,PPI 是“像素有多密”,缩放因子和 DPR 是“系统放大多少倍”,逻辑分辨率是“程序看到多大坐标”,DPI 是“系统认为的密度参考”。理解这条链路,后续的多屏枚举、窗口定位、坐标转换和资源适配都会变得有据可依。