[Qt开发]当我们在开发兼容高分辨率和高缩放比、高DPI屏幕的软件时,我们在谈论什么。

news/2025/3/10 22:06:03/文章来源:https://www.cnblogs.com/Leventure/p/18237406

前言

最近在开发有关高分辨率屏幕的软件,还是做了不少尝试的,当然我们也去网上查了不少资料,但是网上的资料也很零碎,说不明白,这样的话我就做个简单的总结,希望看到这的你可以一次解决你有关不同分辨率下的所有问题。

分辨率?DPI?

首先我们搞清楚我们现在到底面对的是什么场景。在开发高分屏的时候,实际上不仅仅是分辨率高,其附带 的推荐缩放比例往往也会相应的变化

在这里插入图片描述
这个两个数值会直接影响你程序的显示效果,例子我就不举了,关于什么是DPI,什么是分辨率,我这里简单说说

我们假设现在我们开发的软件界面大小是 1000 x 1000,现在测试用的的屏幕都是27寸的屏幕,但是A屏幕是1080p的,即1920x1080,而B屏幕是4K的,即4096×3112,

在这里插入图片描述
看,同样是1000x1000的界面,在1920 x 1080的屏幕上几乎要铺满一大半还要多了,但是在4096x3122的屏幕上,它的宽甚至只占屏幕的1/4。

这就会导致,同样的画面,在1080p的屏幕下显示正常,但是在4k的屏幕上显示就会非常小,小到看不见。

那你可能就要问了,那有没有更好的办法来决定我们的显示呢?


随着屏幕技术的发展,现在高分辨率的屏幕越来越常见了,所以为了解决这个同样大小的程序在不同分辨率下差距过大的问题,Windows引入了一个叫做DPI的概念(Dot per Inch),这个之前打csgo的朋友可能一下就反应过了,是的,鼠标同样有DPI这个概念,而且屏幕DPI和鼠标DPI概念差不多。

DPI指的是图像每英寸(1 英寸 = 25.4 毫米)长度内的像素点数。我们还是应该把像素理解为小方块,dpi就可以理解为是一英寸长度内排列的像素数。通过图像的dpi我们就可以计算出在这个图像中像素的边长,如果也知道图像的分辨率(宽高像素数),就可以知道该图像的真实尺寸了。

当你在Windows的显示设置中调整缩放比例(例如,125%、150%、175%等),实际上是在调整系统级别的DPI设置。这个缩放比例直接影响到系统如何渲染所有的图形用户界面元素,包括字体、图标和整个应用程序窗口。

计算公式如下:

\(实际DPI=基础DPI * \frac{缩放百分比}{100}\)

\(96DPI * 1.5 = 144DPI\)

还有一个概念,点距(dot pitch),就是把像素理解为点的时候,点距就是两个像素点的距离

我们把像素理解为小方块,那点距其实就是像素的边长

点距与DPI之间转换,点距一般用毫米表示,DPI表示1英寸(也就是25.4mm)长度内的像素数,所以点距(像素的边长)就等于 25.4 / DPI(总长度/个数=每个长度)

怎么做

当然了,你肯定对公式不感兴趣,那么我们自然是要说一下怎么解决的。

先说Qt有几个常用的属性。

    //// 启用高DPI缩放QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);// 使用高分辨率的位图(可选)QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
  1. QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

这个函数是用来启用高DPI缩放的。当应用程序在高分辨率的显示设备上运行时,Qt会自动根据系统的DPI设置来缩放界面元素,使得界面在不同分辨率的显示器上具有合适的大小和清晰度。此属性应在创建QApplication对象之前设置。

  1. QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);

这个函数是用来启用高分辨率位图的支持的。当设置为true时,Qt会尝试使用高分辨率版本的位图(如果有的话),以保证在高DPI显示设备上图标和其他图形元素的清晰度。这对于那些使用像素图(如PNG或JPEG图像)作为界面元素的应用程序尤其有用。

难道这样就可以了?

显然只这样做是不够的,如果这样的话,实际上只是启动了Qt程序的DPI支持。你可能会想,那敢情好啊,直接开了DPI支持,是不是就万事大吉了?

答案是错误的,实际上你会遇到三个问题:

  1. 缩放比例错误
    当你尝试缩放的时候,你会发现有时候缩放比例过大,有时候缩放比例又过小,这是为什么呢?

为了解决这个问题,我们需要翻到Qt的文档里面有关这个AA_EnableHighDpiScaling的文章
在这里插入图片描述
对于此,你会惊喜的发现,这个自带的DPI设置似乎会自动指向整数,也就是说,你的缩放比例为1.25时,它的缩放比例就会四舍五入变成1,缩放比例到1.5的时候,缩放比例也就会到2,很可能你用的时候就会直接把屏幕给撑爆了。

  1. 用户的屏幕默认缩放比例本身就是错的
    有时候,特别是有些小的抽象的笔记本,什么动不动十七寸的显示器,分辨率又畸形的高,可能动不动缩放比例就给到2到三,要是程序本身界面就够大,可能直接就给屏幕撑爆了,这是不好的。

  2. 字体显示异常
    正常屏幕上显示
    在这里插入图片描述
    更换了屏幕之后
    在这里插入图片描述

解决方法

  1. 为了解决前面两个问题,我们参考Qt.io上的文档
    High-DPI Support in Qt 5.6

在这里插入图片描述
哇,没想到这个缩放比例可以直接由环境变量设置,那我们就可以将这个缩放比例的环境变量设置为 N/1080,这样我们的程序就会在运行的过程中始终保持其在画面中的比例,而不需要关心比例和分辨率了。

注:你可能想用Qt自带的QScreen去检查屏幕分辨率,但是QScreen不能在QApplication初始化之前使用,但是设置缩放比例又必须在QApplication初始化之前进行,所以

具体操作代码如下:

#include <QApplication>
#include <QDebug>
#include <QString>RECT RetrieveMonitorBounds(int idx) {DISPLAY_DEVICEW dd;dd.cb = sizeof(dd);BOOL flag = EnumDisplayDevicesW(nullptr, idx, &dd, 0);DEVMODEW dm;dm.dmSize = sizeof(dm);dm.dmDriverExtra = 0;flag = EnumDisplaySettingsExW(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm, 0);RECT rect = { dm.dmPosition.x, dm.dmPosition.y, dm.dmPosition.x + dm.dmPelsWidth, dm.dmPosition.y + dm.dmPelsHeight };return rect;
}int main(int argc, char* argv[]) {int monitorCount = ::GetSystemMetrics(SM_CMONITORS);qDebug() << "Detected monitors: " << monitorCount;QString scalingFactors;for (int j = 0; j < monitorCount; ++j) {RECT dimensions = RetrieveMonitorBounds(j);int h = dimensions.bottom - dimensions.top;double scale = (h > 1080) ? (double)h / 1080.0 : 1.0;scalingFactors += (j == 0 ? "" : ";") + QString::number(scale, 'f', 1);}QByteArray envVar = scalingFactors.toUtf8();qputenv("QT_SCREEN_SCALE_FACTORS", envVar);// Enable high DPI scalingQApplication::setAttribute(Qt::AA_EnableHighDpiScaling);// Optionally use high resolution pixmapsQApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);QApplication app(argc, argv);QMainWindow mainWindow;mainWindow.show();return app.exec();
}
  1. 关于字体缩放不当
    首先我们要搞清楚有关字体大小的一些设置

我们知道对于Qt来说,他们是很喜欢用Pt这个单位的,几乎所有默认的单位都是Pt,但是实际上又有另外一个单位px,我们需要先搞清楚这两个单位是做什么的

  1. 点(pt):点是传统的印刷行业使用的度量单位,1点等于1/72英寸。在显示设备上,使用点作为字体大小的单位时,Qt会根据系统的DPI(每英寸点数)设置来调整字体的实际像素大小。例如,在96 DPI的显示器上,1点大约等于1.333像素。使用点作为单位设置字体大小时,字体的大小会根据不同的显示器分辨率自动调整,以保持视觉上的一致性。
  1. 像素(px):像素是计算机显示领域的一个基本单位,直接对应屏幕上的一个显示点。在Qt中以像素为单位设置字体大小意味着无论DPI设置如何,字体的大小始终以固定的像素数显示。这会导致在不同DPI设置的显示器上,相同像素值的字体大小视觉上可能会有很大差异。

这种自动缩放的目的是确保在高分辨率显示器上元素保持适当的物理大小,从而提升用户体验。然而,这种自动缩放可能导致在不同分辨率和 DPI 设置下,使用点单位设置的字体大小出现视觉上的不一致,因为点单位本身是与物理尺寸(1/72 英寸)相关的,而屏幕 DPI 会影响这一转换关系。

使用 点(pt) 设置字体或大小时,这些设置会根据系统的 DPI 自动缩放,以尝试保持物理上的一致性,从而在高 DPI 显示器上可能看起来过大或过小。

使用 像素(px) 设置时,元素的大小直接映射到屏幕的像素,不会根据 DPI 进行自动调整,因此在高 DPI 设置下可能看起来偏小,因为更多的像素被压缩在了物理尺寸相同的空间内。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/721436.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Maui+blazor中使用https时信任所有证书

Maui中的Android使用https时信任所有证书 前言 最近使用Maui+blazor写了一个Android app,需要调用webapi接口,同时需要用websock与服务器通信,在使用http和https中遇到一些问题 http Android默认禁止http,想要使用http需要在Platforms\Android目录下找到AndroidManifest.xml…

文件格式转换器哪个工具更好用?

文件格式转换器哪个好用?相信很多小伙伴在处理PDF文件时会遇到各种各样的问题,不晓得的选择哪款文件格式转换器!这个时候我们该如何解决呢?以下是文件格式转换器推荐,一起来看看吧。 一、Adobe Acrobat 推荐指数★★★☆☆ Adobe Acrobat是一款非常成熟的在线PDF转换软件,…

yarn或者npm安装依赖报错401 Unauthorized

1. 报错2.原因 在npm顶层的npmrc中指定了某仓库地址,触发了需要验证(可以通过直接打开401的地址看浏览器是否能直接下载)

pr的工作原理

Premiere Pro了解pr面板菜单栏:里面包括文件,编辑,剪辑,序列,标记,窗口,帮助等,在这些菜单里还有子菜单。效果面板:双击素材,可以在效果面板里进行编辑你想要的效果。节目面板:在时间轴里编辑时,要是查看效果在节目面板里进行查看。项目面板:导入和新建的素材都可…

ARM技术 —— 条件执行

文档: DDI0487J_a_a-profile_architecture_reference_manual.pdf本文来自博客园,作者:摩斯电码,未经同意,禁止转载

pr工作原理文档

Adobe Premiere Pro的工作原理思维导图 Pr面板展示图 第一步:导入视频1导入点击文件——点击导入——选择视频,双击视频或点击打开按钮——完成导入。2预览点击视频,拖到右侧;拖动蓝色条,时间指针,点击会快速预览,快捷键是空格键。3视频轨道和音频轨道A声音;V:视频;左…

vue3+TypeScript

1. Vue3简介2020年9月18日,Vue.js发布版3.0版本,代号:One Piece(n经历了:4800+次提交、40+个RFC、600+次PR、300+贡献者官方发版地址:Release v3.0.0 One Piece vuejs/core截止2023年10月,最新的公开版本为:3.3.41.1. 【性能的提升】打包大小减少41%。初次渲染快55%, …

pr工作原理

Pr图像式基础课一新建项目二新建序列下一页看后续三颜色调出Lumetri颜色,色轮部分就可以进行颜色的调整(个人)四认识三面板与效果效果控件是pr软件的重要组成部分,它可以对视频效果的调节时间轴上可以进行调节与裁剪无用的视频段画面的展示和查看搜索查找效果五工具的认识选…

FastAPI-4:异步、并发和Starlette

4 异步、并发和Starlette 本章关注FastAPI的底层Starlette库,尤其是它对异步处理的支持。在概述了Python中“同时做更多事情”的多种方法后,您将看到Python中较新的async和await关键字是如何融入Starlette和FastAPI的。4.1 Starlette FastAPI 的大部分网络代码都基于 Tom Chr…

实验6_C语言结构体、枚举应用编程

实验任务4#include <stdio.h> #define N 10typedef struct {char isbn[20]; // isbn号char name[80]; // 书名char author[80]; // 作者double sales_price; // 售价int sales_count; // 销售册数 } Book;void output(Book x[], int…

k8s里node 宕机后如何提高pod迁移速度

大概的配置参数:node故障后,pod会迁移到 正常的node上, 迁移时间大概8分钟左右, 如果是微服务,注册到nacos,服务不受影响,但是对于其他的服务,请求中会有大量失败。需要几个流程: kubelet 自身会定期更新状态到 apiserver,通过kubelet的参数 node-status-update-freq…

day11 Xpath

网页分析有优势,全称XML Path Language一种小型的查询语言 优点:可在XML中查询信息 支持HTML的查询 通过元素和属性进行导航 PY使用需要安装库:安装lxml selector = etree.HTML(html_doc)//实例化对象,实际上就是一个Element类,通过逻辑运算: //div[@id and @class]查找…