当前位置: 首页 > news >正文

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

前言

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

分辨率?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设置。这个缩放比例直接影响到系统如何渲染所有的图形用户界面元素,包括字体、图标和整个应用程序窗口。

计算公式如下:

实际 D P I = 基础 D P I ∗ 缩放百分比 100 实际DPI=基础DPI * \frac{缩放百分比}{100} 实际DPI=基础DPI100缩放百分比

96 D P I ∗ 1.5 = 144 D P I 96DPI * 1.5 = 144DPI 96DPI1.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 设置下可能看起来偏小,因为更多的像素被压缩在了物理尺寸相同的空间内。

相关文章:

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

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

uniapp视频组件层级太高,解决方法使用subNvue原生子体窗口

目录 前言 先看一下uniapp官网的原话&#xff1a; subNvue的一些参数介绍 subNvues使用方法&#xff1a; 绑定id 显示 subNvue 弹出层 subNvue.show() 参数信息 subNvue.hide() 参数信息 在使用subNvue 原生子体窗口 遇到的一些问题 前言 nvue 兼容性 以及使用方式 控…...

java项目使用jsch下载ftp文件

pom <dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version> </dependency>demo1&#xff1a;main方法直接下载 package com.example.controller;import com.jcraft.jsch.*; im…...

指针(初阶1)

一.指针是什么 通俗的讲&#xff0c;指针就是地址&#xff0c;其存在的意义就像宾馆房间的序号一样是为了更好的管理空间。 如下图&#xff1a; 如上图所示&#xff0c;指针就是指向内存中的一块空间&#xff0c;也就相当于地址 二.一个指针的大小是多少 之前我们学习过&#x…...

MySQL实体类框架

实现mysql数据库的增删改查功能 import com.mchange.v2.collection.MapEntry; import lombok.Data; import org.junit.jupiter.api.Test;import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.*; import java.sql.*; …...

数据结构之初始泛型

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 深入了解包装类 包装类的由来 装箱与拆箱 面试题 泛型 泛型的语法与使用…...

【网络编程开发】7.TCP可靠传输的原理

7.TCP可靠传输的原理 TCP实现可靠传输的原理主要基于序列号和确认应答、超时重传、滑动窗口、连接管理机制以及拥塞控制等多重机制。 TCP&#xff08;Transmission Control Protocol&#xff09;&#xff0c;即传输控制协议&#xff0c;是网络通信中的一种重要协议&#xff0…...

视觉SLAM十四讲:从理论到实践(Chapter8:视觉里程计2)

前言 学习笔记&#xff0c;仅供学习&#xff0c;不做商用&#xff0c;如有侵权&#xff0c;联系我删除即可 一、目标 1.理解光流法跟踪特征点的原理。 2.理解直接法是如何估计相机位姿的。 3.实现多层直接法的计算。 特征点法存在缺陷&#xff1a; 二、光流(Optical Flow) …...

C语言过度C++语法补充(面向对象之前语法)

目录 1. C相较于C语言新增的语法 0. C 中的输入输出 1. 命名空间 1. 我们如何定义一个命名空间&#xff1f; 2. 如何使用一个命名空间 3. 命名空间中可以定义什么&#xff1f; 4. 在 相同或者不同 的文件中如果出现 同名的命名空间 会如何&#xff1f; 5. 总结~~撒花~~…...

类和对象(二)(C++)

初始化列表 class Date{public:Date(int year, int month, int day){_year year;_month month;_day day;}private:int _year;int _month;int _day;}; 虽然上述构造函数调用之后&#xff0c;对象中已经有了一个初始值&#xff0c;但是不能将其称为对对象中成员变量的初始化…...

Chrome DevTools解密:成为前端调试大师的终极攻略

Chrome DevTools是一套内置于Google Chrome浏览器中的开发者工具&#xff0c;它允许开发者对网页进行调试、分析和优化。本文将全面介绍DevTools的功能、使用方法以及注意事项&#xff0c;帮助开发者更好地利用这些工具来提升开发效率和网页性能。 一、简介 1. DevTools是什么…...

【python】OpenCV—Cartoonify and Portray

参考来自 使用PythonOpenCV将照片变成卡通照片 文章目录 1 卡通化codecv2.medianBlurcv2.adaptiveThresholdcv2.kmeanscv2.bilateralFilter 2 肖像画cv2.divide 1 卡通化 code import cv2 import numpy as npdef edge_mask(img, line_size, blur_value):gray cv2.cvtColor(…...

制作AI问答机器人:从0到1的完整指南

在数字化转型的浪潮中&#xff0c;企业正追求更高效、智能的客户服务解决方案。AI问答机器人以其快速响应、全天候服务和持续学习的能力&#xff0c;成为了提升客户满意度和加速业务发展的关键工具。本文将深入探讨如何制作一个企业级的AI问答机器人&#xff0c;并强调其功能体…...

mysql 数据库datetime 类型,转换为DO里面的long类型后,只剩下年了,没有了月和日

解决方法也简单&#xff1a; 自定义个一个 Date2LongTypeHandler <resultMap id"BeanResult" type"XXXX.XXXXDO"><result column"gmt_create" property"gmtCreate" jdbcType"DATE" javaType"java.lang.Long&…...

信息系统项目管理师0148:输出(9项目范围管理—9.3规划范围管理—9.3.3输出)

点击查看专栏目录 文章目录 9.3.3 输出 9.3.3 输出 范围管理计划 范围管理计划是项目管理计划的组成部分&#xff0c;描述将如何定义、制定、监督、控制和确认项 目范围。范围管理计划用于指导如下过程和相关工作&#xff1a; ①制定项目范围说明书&#xff1b;②根据详细项目范…...

解决 SQLyog 连接 MySQL 8 连不上和 SQLyog Trial 试用到期的问题

今天发现 SQLyog 突然连不上 MySQL 了&#xff0c;跟之前不一样的地方就是我升级了 MySQL&#xff0c;升级到了 MySQL 8。 原来是因为 MySQL 8 引入了新的密码验证机制。在 MySQL 8 中默认的密码验证插件从 mysql_native_password 更换为 caching_sha2_password。我的 SQLYog …...

go语言内置预编译 //go:embed xxx 使用详解

在go语言里面&#xff0c;我们可以使用一个“类注释”的语法来来让编译器帮助我们在编译的时候将一些文件或者目录读取到指定的变量中来供我们使用。 go:embed语法&#xff1a; //go:embed 文件或者目录路径 var 变量名 变量类型 说明&#xff1a; 文件或者目录路径 可以…...

数据挖掘--挖掘频繁模式、关联和相关性:基本概念和方法

频繁项集、闭项集和关联规则 频繁项集&#xff1a;出现的次数超过最小支持度计数阈值 闭频繁项集&#xff1a;一个集合他的超集(包含这个集合的集合)在数据库里面的数量和这个集合在这个数据库里面的数量不一样,这个集合就是闭项集 如果这个集合还是频繁的,那么他就是极大频…...

Locust:用Python编写可扩展的负载测试

Locust&#xff1a;简化性能测试&#xff0c;让负载模拟更直观- 精选真开源&#xff0c;释放新价值。 概览 Locust是一个开源的性能和负载测试工具&#xff0c;专门用于HTTP和其他协议的测试。它采用开发者友好的方法&#xff0c;允许用户使用普通的Python代码来定义测试场景。…...

【Neo4j】Windows11使用Neo4j导入CSV数据可视化知识图谱

Windows11使用Neo4j导入CSV数据可视化知识图谱 序1. 安装JDK21&#xff08;1&#xff09;下载&#xff08;2&#xff09;安装&#xff08;3&#xff09;环境配置 2. 安装Neo4j&#xff08;1&#xff09;下载&#xff08;2&#xff09;解压安装&#xff08;3&#xff09;环境配置…...

探索智慧林业系统的总体架构与应用

背景&#xff1a; 随着人们对森林资源保护和管理的重视&#xff0c;智慧林业系统作为一种新兴的林业管理手段&#xff0c;正在逐渐受到广泛关注和应用。智慧林业系统的总体架构设计与应用&#xff0c;将现代信息技术与林业管理相结合&#xff0c;为森林资源的保护、管理和利用…...

【JSP】如何在IDEA上部署JSP WEB开发项目

以我的课设为例&#xff0c;教大家拿到他人的项目后&#xff0c;如何在IDEA上部署。 需要准备&#xff1a; JDK17&#xff08;或者JDK13&#xff09;IntelliJ IDEA 2023.2.6MySQL 8.0Tomcat 9.0 一&#xff0c;新建项目添加文件 1.1复制“位置”的路径 1.2找到该文件夹 1.3…...

用HTML实现拓扑面,动态4D圆环面,可手动调节,富有创新性的案例。(有源代码)

文章目录 前言一、示例二、目录结构三、index.html&#xff08;主页面&#xff09;四、main.js五、Tour4D.js六、swissgl.js七、dat.gui.min.js八、style.css 前言 如果你觉得对代码进行复制粘贴很麻烦的话&#xff0c;你可以直接将资源下载到本地。无需部署&#xff0c;直接可…...

java调用GDAL及JTS实现生成泰森多边形(Voronoi图)的一种方法

目录 一、关于泰森多边形 1.泰森多边形的特性 2.本文的目的 二、实现思路 1.gdal和jts库的maven坐标 2.jts生成泰森多边形的关键代码 3.使用GDAL读取源文件信息的关键代码 4.使用GDAL将生成的泰森多边形写入文件 三、实现结果 1.实现的效果 2.完整代码示例 一、关于…...

Type-C音频转接器方案

在数字化时代&#xff0c;音频设备作为我们生活中不可或缺的一部分&#xff0c;其连接方式的便捷性和高效性显得尤为重要。Type-C音频转接器&#xff0c;作为一种新型的音频连接解决方案&#xff0c;正逐渐走进我们的生活&#xff0c;以其独特的优势改变着我们的音频体验。 一、…...

linux 服务器上离线安装 node nvm

因为是离线环境 如果你是可以访问外网的 下面内容仅供参考 也可以继续按步骤来 node 安装路径 Node.js — Download Node.js nvm 安装路径 Tags nvm-sh/nvm GitHub 后来发现 nvm安装后 nvm use 版本号 报错 让我去nvm install 版本 我是内网环境 install不了 下面 你要 把安…...

Web前端三大主流框架:React、Angular和Vue的比较与选择

Web前端三大主流框架&#xff1a;React、Angular和Vue的比较与选择 Web前端技术的快速发展为开发者提供了丰富的工具和框架&#xff0c;其中React、Angular和Vue是当前最受欢迎的三大框架。这三个框架各有特点&#xff0c;适用于不同的项目需求和开发团队。本文将对React、Ang…...

C# MemoryCache 缓存应用

摘要 缓存是一种非常常见的性能优化技术&#xff0c;在开发过程中经常会用到。.NET提供了内置的内存缓存类 MemoryCache&#xff0c;它可以很方便地存储数据并在后续的请求中快速读取&#xff0c;从而提高应用程序的响应速度。 正文 通过使用 Microsoft.Extensions.Caching.Me…...

【学习笔记】Linux前置准备

视频学习资料 基础&#xff1a; 黑马0基础&#xff08;前面四章即可&#xff0c;包含软件基础安装配置&#xff09; 进阶&#xff1a; 黑马程序员-Linux系统编程 黑马程序员-Linux网络编程 我也还没看&#xff0c;看了眼目录感觉把八股里面很多场景都讲到了&#xff0c;感觉有…...

各种空气能热泵安装图

空气能热泵安装图 循环式空气能热泵安装图 直热循环式空气能热泵安装图 泳池空气能热泵安装图 循环式水源热泵热安装系统原理图 直热循环式水源热泵安装系统图 空气水源热泵安装图...

购物商城app/seo海外

计算机故障的一小知识不求人 巧用Win 7查看无线网络密码为了禁止非授权电脑的接入&#xff0c;无线局域网网络环境一般都会设置密码。若是新电脑要进入加密的无线网&#xff0c;通常需要找网络管理员获取无线网密码授权才能接入。不过&#xff0c;若是管理员不在&#xff0c;新…...

wordpress相对路径设置/高端网站建设哪个好

Vue JSX Vue JSX 语法 参考文章&#xff1a;在Vue3.0中使用JSX的简单入门_咲奈的博客-CSDN博客_vue3使用jsxVue3 使用 jsx_沿着路走到底的博客-CSDN博客_vue3 使用jsx在vue3中使用jsx语法_艳子的皮皮猪的博客-CSDN博客_vue3使用jsx【组件库从0到1】Vite Vue3 TSX开发指南…...

wordpress主题图片修改/介绍网络营销的短文

本来今年提前60天抢票以为可以抢到自己心仪的票&#xff0c;高高兴兴的回家去的&#xff0c;可是天不从人意&#xff0c;各种抢票软件都使用了还是没有抢到票&#xff0c;最后还是通过Q群的黄牛买到了票。 虽然最近12306发生的信息泄露问题&#xff0c;我也上去修改了密码&…...

做婚庆网站有哪些内容/seo好学吗入门怎么学

文章目录linux 下构建NTP时间服务器及客户端同步NTP 概述NTP 基础命令搭建NTP服务器案例演示总结linux 下构建NTP时间服务器及客户端同步 NTP 概述 前言 在公司环境中&#xff0c;如果他们不想为 NTP 传输打开防火墙&#xff0c;就有必要设置一个内部 NTP 服务器&#xff0c;然…...

做分析图的网站/深圳网络营销平台

七步从Angular.JS菜鸟到专家&#xff08;3&#xff09;&#xff1a;数据绑定和AJAX 这是&#xff02;AngularJS - 七步从菜鸟到专家&#xff02;系列的第三篇。 在第一篇&#xff0c;我们展示了如何开始搭建一个AngularaJS应用。第二篇我们讨论了scope和 $scope 的功能。 通过这…...

电影下载网站模板/网站推广及seo方案

目录 01 准备演讲内容 02 快速掌握「抑扬顿挫」技巧 03 准备完整的演讲稿 04 害怕在公众面前发言怎么办? 05 如何面对冷场&#xff1f; 06 「好口才人士」具备的7个说话习惯 07 跟柴静学演讲技巧 01 准备演讲内容 02 快速掌握「抑扬顿挫」技巧 03 准备完整的演讲稿 04 害怕在…...