Qt应用的高分辨率适配

news/2024/9/18 21:09:13/ 标签: qt, 开发语言, c++

背景

工作中需要面对触控大屏的4K分辨率场景,同时也有越来越多人开始使用高分屏,原来多基于1080p分辨率开发的Qt程序无法很好适配更高的分辨率。
没有特意针对高分辨率场景做适配时,Qt应用的表现通常有两种情况:

  • 分辨率高的情况下,应用界面显示特别小
  • 应用界面显示的大小跟随缩放比例的设置,但又没有完全跟随

问题分析

想要解决以上问题,首先需要了解Qt的分辨率适配机制,再根据机制分析问题原因。

Qt提供的分辨率适配能力

1、Qt::AA_EnableHighDpiScaling属性
从Qt5.6开始,支持通过QApplication::setAttribute(Qt::AA_EnableHighDpiScaling)启用高DPI缩放。设置之后,Qt会自动根据系统的DPI设置来缩放界面元素,此属性需要在创建QApplication对象之前设置。
注意:Qt5.6中引入了Qt::AA_DisableHighDpiScaling属性关闭所有缩放,优先级高于Qt::AA_EnableHighDpiScaling。

2、环境变量缩放
同样是从Qt 5.6开始支持,此处引用Qt官方文档内容:

  • QT_AUTO_SCREEN_SCALE_FACTOR[boolean] :启用基于显示器像素密度的自动缩放,这不会更改磅值字体的大小,多个屏幕可能会获得不同的比例系数
  • QT_SCALE_FACTOR[numeric]:定义整个应用程序的全局缩放因子,包括磅大小的字体
  • QT_SCREEN_SCALE_FACTORS[list]:指定每个屏幕的缩放系数,不会更改磅值字体的大小

3、缩放策略设置
从Qt5.14开始,支持使用以下接口进行缩放策略设置 :

QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);

在这里插入图片描述
4、Qt6的缩放策略
从Qt6.0开始默认开启Qt::AA_EnableHighDpiScaling,而且不允许关闭,但可以通过setHighDpiScaleFactorRoundingPolicy函数影响缩放策略。

问题分析

1、分辨率高的情况下,应用界面显示特别小
由于Qt6.0之后才默认开启Qt::AA_EnableHighDpiScaling自动缩放,在此之前的版本,应用没有实现任何分辨率适配的逻辑,且最开始界面设计是按照1080p的尺寸实现,在高分辨率时自然显示特别小。
2、应用界面显示的大小跟随缩放比例的设置,但又没有完全跟随
Qt应用启用了Qt::AA_EnableHighDpiScaling的情况下,会自动进行缩放调整,但自动调整的默认策略是对系统的缩放比例进行四舍五入,所以会有差异。

解决方案

在了解Qt的分辨率适配机制,并分析出原因后,可以根据自己的缩放需求进行分辨率适配。
1、希望跟随系统缩放比例进行缩放
这种方式比较简单,可通过以下方式实现:

int main(int argc, char *argv[])
{QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);  // 此处根据希望实现的缩放策略进行设置QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);QApplication a(argc, argv);ExampleWidget w;w.show();return a.exec();
}

2、无论系统分辨率及缩放比例如何设置,应用显示大小和屏幕始终保持相对一致
这种方式无论如何修改分辨率和缩放比例,应用在屏幕上显示的大小,始终保持不变。
需要处理两个地方,第一是在QApplication之前设置QT_SCALE_FACTOR环境变量:

void useCustomScale()
{// 分辨率适配(Qt6之前可采用这个方式,Qt6之后可能会强制使用默认适配,可能需要找其他方法禁用默认适配规则)QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);  // 禁用Qt默认适配QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);// 采用自定义的缩放设置:不关心系统缩放设置,根据屏幕分辨率设置缩放比例// 同时保持程序宽高相对屏幕大小固定(这一点需要设置程序窗口fixedsize时进行)int screenWidth = 0;int screenHeight = 0;#ifdef __linux__Display *display = XOpenDisplay(NULL);if (nullptr == display){return;}Screen *screenInfo = ScreenOfDisplay(display, DefaultScreen(display));if (nullptr != screenInfo){screenWidth = screenInfo->width;screenHeight = screenInfo->height;}XCloseDisplay(display);
#endif#ifdef _WIN32HDC hdc_screen = GetDC(0);screenWidth = GetDeviceCaps(hdc_screen, DESKTOPHORZRES);screenHeight = GetDeviceCaps(hdc_screen, DESKTOPVERTRES);ReleaseDC(0, hdc_screen);
#endif// 应用是基于1080p设计开发,因此以1080p为基准double scale = (double)screenWidth / 1920;if (scale < 1.25) { scale = 1.0; }else if (scale >= 1.25 && scale < 1.75) { scale = 1.5; }else if (scale >= 1.875) { scale = 2.0; }// 由于该变量需要在app之前调用,所以QScreen无法使用,需要用系统的获取屏幕分辨率接口QString scaleFactor = QString::number(scale, 'f', 1);qputenv("QT_SCALE_FACTOR", QByteArray::fromStdString(scaleFactor.toStdString()));
}

另外,需要设置程序宽高相对屏幕大小固定:

    QRect screenGeometry = QApplication::desktop()->screenGeometry();int screen_width = screenGeometry.width();int screen_height = screenGeometry.height(); // 应用是基于1080p设计开发,因此以1080p为基准setFixedSize(fixedWidth / 1920 * screen_width, fiexdHeight / 1080 * screen_height);

其他注意点

以上的方法能够实现应用整体的缩放适配,但是应用内部的文字、图像等内容,在缩放时还是有可能会出现问题,以下简单例举几种情况:
1、设置缩放策略后,有可能出现图片/图标模糊的情况。尽量使用SVG图,同时可以通过QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps)优化模糊。
2、通过QPainter的方式实现绘制文字时,setPixelSize和setPointSize可适应于不同的缩放策略。


http://www.ppmy.cn/news/1518619.html

相关文章

波导阵列天线单元学习笔记7 一种用直接金属激光烧结考虑的轻质量,宽带,双圆极化波导腔体阵列

摘要&#xff1a; 提出了一种工作在Ku频段的轻质量&#xff0c;宽带&#xff0c;双圆极化波导腔体阵列。为了获得双正交的线极化&#xff0c;基本的辐射单元是由两个波导馈电的方形腔体。通过恰当地对馈网进行调谐&#xff0c;可以获得对于两个正交极化的等辐同相辐射电场&…

智能指针(RAII)

智能指针&#xff08;RAII&#xff09; 一、内存泄漏1、介绍2、原因3、泄漏的内存类型分类 二、RAII1、介绍2、基本思想3、优点4、实现方式 三、unique_ptr1、介绍2、主要特性3、注意事项4、unique_ptr类5、示例代码6、运行结果7、简单实现 四、shared_ptr1、介绍2、主要特点3、…

如何处理时间序列异常值?理解、检测和替换时间序列中的异常值

异常值的类型 (欢迎来到雲闪世界) 异常值是与正常行为有显著偏差的观察结果。 时间序列可能会因某些异常和非重复事件而出现异常值。这些异常值会影响时间序列分析&#xff0c;并误导从业者得出错误的结论或有缺陷的预测。因此&#xff0c;识别和处理异常值是确保时间序列建模…

【TDesign】如何修改CSS变量

Tdesign的组件想通过style定义样式没效果, 可以通过组件api文档修改, 组件提供了下列 CSS 变量&#xff0c;可用于自定义样式。 比如Cell, https://tdesign.tencent.com/miniprogram/components/cell?tabapi 提供了&#xff1a; –td-cell-left-icon-color 图标颜色 –td-cell…

【Leetcode 2341 】 数组能形成多少数对 —— 去重

给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;你可以执行以下步骤&#xff1a; 从 nums 选出 两个 相等的 整数从 nums 中移除这两个整数&#xff0c;形成一个 数对 请你在 nums 上多次执行此操作直到无法继续执行。 返回一个下标从 0 开始、长度为 2 的…

电脑变声器软件哪个好用?最新款实时变声器数据公开!

电脑变声器软件哪个好用&#xff1f;什么场合下需要用到变声器&#xff1f;在派对或朋友聚会中&#xff0c;使用变声器可以模仿各种动物、名人或虚构角色的声音&#xff1b;直播变声搞怪&#xff1b;匿名游戏聊天&#xff1b;电影、动画、电视音效、旁白制作等等&#xff0c;都…

高职院校大数据分析与可视化微服务架构实训室解决方案

一、前言 随着信息技术的飞速发展&#xff0c;大数据已成为推动社会进步与产业升级的关键力量。为了培养适应未来市场需求的高素质技术技能型人才&#xff0c;高职院校纷纷加大对大数据分析与可视化技术的教学投入。唯众&#xff0c;作为国内领先的职业教育解决方案提供商&…

2 Python开发工具:PyCharm的安装和使用

本文是 Python 系列教程第 2 篇&#xff0c;完整系列请查看 Python 专栏。 1 安装 官网下载地址https://www.jetbrains.com.cn/pycharm/&#xff0c;文件比较大&#xff08;约861MB&#xff09;请耐心等待 双击exe安装 安装成功后会有一个30天的试用期。。。本来想放鸡火教程&…

Nginx负载均衡请求队列配置:优化流量管理

在高流量的Web应用场景中&#xff0c;合理地管理进入的请求流量对于保持服务的稳定性和响应性至关重要。Nginx提供了请求队列的配置选项&#xff0c;允许开发者控制进入后端服务器的请求数量。通过配置请求队列&#xff0c;可以在后端服务器达到最大处理能力时&#xff0c;优雅…

005、架构_数据节点

​DN组件总览 ​ DN节点包含进程 dbagent进程:主要提供数据节点高可用、数据导入导出、数据备份恢复、事务一致性、运维类功能、集群的扩缩容、卸数等功能;MySQL进程:主要提供数据一致性、分组管理、快同步复制、高低水位等;

测试岗位应该学什么

以下是测试岗位需要学习的一些关键内容&#xff1a; 1. 测试理论和方法 - 了解不同类型的测试&#xff0c;如功能测试、性能测试、压力测试、安全测试、兼容性测试等。 - 掌握测试策略和测试计划的制定。 2. 编程语言 - 至少熟悉一种编程语言&#xff0c;如 Python、Java…

网络路由介绍,route指令,查询路由表的过程,默认路由

目录 路由 本地主机的路由功能 引入 route指令 查询路由表的过程 介绍 示例 默认路由 注意 路由 本地主机的路由功能 引入 报文经过多个路由器转发至公网,再从公网定位后转发至私网,最终到达目标主机 而报文肯定是要先经过本地主机的 所以本地主机也具有路由功能,也…

django网吧收费管理系统 项目源码26819

摘 要 随着互联网的普及&#xff0c;网吧作为公共互联网接入场所&#xff0c;依旧在许多地区发挥着重要作用。现代网吧不仅仅是提供上网服务的场所&#xff0c;还包括了游戏、社交、休闲等多功能体验。为了提高网吧的服务质量和运营效率&#xff0c;迫切需要一个高效的管理系统…

mysql基础语法——个人笔记

0 前言 以前学习且实践过mysql&#xff0c;但后来用得少&#xff0c;随着岁月更替&#xff0c;对其印象渐浅&#xff0c;所以每次需要用时&#xff0c;都会去再看一眼语法规范&#xff0c;然后才能放心动手操作 然而&#xff0c;在信息爆炸的时代&#xff0c;查语法规范时&am…

ubuntu录屏解决ubuntu下无法播放MP4格式文件的方法

参考 gnome gnome是系统自带的录屏&#xff0c;通过ctrlshiftaltr触发 保存到了视频目录下&#xff0c;webm格式文件。 screencastify 这是一个chrome扩展&#xff0c;&#xff0c;一般不推荐使用 recapp 比gnome自由一些&#xff0c;可以自由屏幕录制。但是无法修改录制…

如何将Dxf文件中的Vertex与相应的polyline关联起来

在处理DXF&#xff08;Drawing Exchange Format&#xff09;文件时&#xff0c;将VERTEX和相应的POLYLINE关联起来是一个常见的需求。这通常涉及解析DXF文件中的几何实体&#xff0c;并确保它们之间的关系正确。以下是一些步骤和示例代码&#xff0c;帮助你实现这种关联&#x…

如果学流式系统你想选一本书,那必须是这本

“如果你关心流式处理和批处理工作的正确性&#xff0c;那么这本书是必读的。它对该主题的讨论是我看到的思考最清晰、最合逻辑的&#xff0c;其思想也被精彩诠释。” ——马丁克莱普曼&#xff08;Martin Kleppmann&#xff09;&#xff0c;剑桥大学 流式系统 如今&#xff0c…

关于mysql的information_schema库表对象

MySQL的information_schema库是一个非常重要的系统数据库&#xff0c;它存储着关于MySQL服务器中所有其他数据库的元数据&#xff08;meta-data&#xff09;。元数据是指关于数据的数据&#xff0c;比如数据库名、表名、列名、数据类型、权限信息等&#xff0c;并不包含实际业务…

Django 后端架构开发:高效测试自动化工具

Django 后端架构开发&#xff1a;高效测试自动化工具 目录 &#x1f6e0; nose&#xff1a;强大的测试框架 &#x1f3ad; faker&#xff1a;模拟数据生成器 &#x1f5a5; PyAutoGUI&#xff1a;跨平台 GUI 自动化测试 &#x1f9ea; coverage&#xff1a;代码覆盖率测量 …

【C++】容器vector常用接口详解

目录 一.vector基本介绍 二.vector的构造&#xff08;constructor&#xff09; 三.vector迭代器&#xff08;iterator&#xff09; 四.vector的三种遍历 1.for循环 2.范围for 3.迭代器&#xff08;正向、反向&#xff09; 五. vector扩容操作 1.reserve 2.resize 六.…