Qt5 高分辨率支持

news2024/10/9 6:23:59

1. 结论

先说结论,在Qt5版本没有比较完美的解决方案。如果使用Qt系统提供的支持方式会出现各种小问题。如果可以的,建议升级为Qt6版本,能够更好支持高分辨率屏。而最终我在Qt5.12.12版本中,采用的方案是通过各种方法组合解决。
详细可参考知乎回答目前Qt有没有比较好解决高分屏下缩放显示的方案?

2. Qt系统自带解决方案说明

2.1 设置环境缩放

  1. qputenv(“QT_AUTO_SCREEN_SCALE_FACTOR”, “2”);
  2. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

上面两种实现本质差不多。第一种设置环境参数的需要根据dpi计算缩放比例。第二种则系统自动进行缩放。该方案能够简单实现高分辨率屏的支持,如果使用建议直接使用第二种即可。
该方案的问题:在于在Qt5.14.x以下版本,只支持整数倍缩放。
在这里插入图片描述

  • 在设置为100% ~ 149%范围内,Qt缩放的倍数为1。
  • 在设置为150% ~ 249%范围内,Qt缩放的倍数为2。
  • 在设置为250% ~ 349%范围内,Qt缩放的倍数为3。
  • 往后依次类推。
    这导致了当系统设置为150%,Qt程序界面会缩放成2倍,看起来效果非常的大,与系统并不协调。

2.2 使用标准配置文件

在资源qrc里添加qt.conf文件,qt/etc/qt.conf, 内容为:

[Platforms]
WindowsArguments = dpiawareness=0

这方案使得Qt程序让windows系统接管控制缩放,整体比例协调,实现简单。
缺点在于会导致界面的模糊,在我电脑测试中,效果十分模糊,个人不太接受。

2.3 结论

有条件的升级为Qt6版本,支持效果更好。无法升级的,根据实际情况选择一种接受的方案。

3. 组合方案

由于作者对于Qt自带的解决方案都不满意, 于是只好一步一步解决。

3.1 解决字体问题

所有的字体使用pt单位,不是用px单位。转换公式为 pt = px * 3 / 4,比如12px * 3 / 4 = 9pt大小。

QFont font("Microsoft YaHei");
// 小数使用
font.setPointSizeF(10.5);
// 整数使用
font.setPointSize(10);
app.setFont(font);

qss中也改为pt单位。

QMenuBar {
	background: #F6F6F6;
	font: 10.5pt;
}

pt单位的字体,系统根据分辨率缩放字体大小,详细可查看文章pt和px的区别是什么。

3.2 解决尺寸问题

获取系统当前的dpi,与96相除得到当前系统的缩放比例,ui使用dpi=96设计界面,根据尺寸进行按比例拉伸。包括layout布局的margins,spacing属性也需要同步拉伸(如果没修改过默认的layout的margins,spacing属性,Qt底层其实会自动拉伸的,不过为了方便我对全局的布局器都一同拉伸)。

/**
  * @file   style_helper.h
  */

#ifndef STYLE_HELPER_H
#define STYLE_HELPER_H

#include <QSize>

class QWidget;
class QLayout;

class StyleHelper
{
public:
  explicit StyleHelper();

  static QSize mainwindowSize();
  static QSize mainwindowSubSize();
  static QSize dialogSize();

  static qreal dpiScaled(qreal value);
  static void sizeScaled(QWidget *widget);

private:
  ///< 屏幕分辨率
  static qint32 my_window_width_;
  static qint32 my_window_height_;
  ///< 屏幕dpi值
  static qint32 my_window_dpi_;
  ///< 屏幕缩放倍数
  static qreal my_window_scale_;
};

#endif // STYLE_HELPER_H
/**
  * @file   style_helper.cpp
  */
#include <QScreen>
#include <QWidget>
#include <QLayout>
#include <qformlayout.h>
#include <QApplication>

#include "style_helper.h"


qint32 StyleHelper::my_window_width_ = 1920;
qint32 StyleHelper::my_window_height_ = 1080;
qint32 StyleHelper::my_window_dpi_ = 96;
qreal StyleHelper::my_window_scale_ = 0;

/**
 * @brief       构造函数
 */
StyleHelper::StyleHelper()
{
  QScreen *screen = QApplication::primaryScreen();
  my_window_width_ = screen->geometry().width();
  my_window_height_ = screen->geometry().height();
  my_window_dpi_ = screen->logicalDotsPerInchX();

  // ui设计使用dpi = 96
  my_window_scale_ = qreal(my_window_dpi_) / 96.0;
}

/**
 * @brief       根据dpi计算缩放尺寸
 * @param[in]   value     设计时尺寸
 * @return      缩放后尺寸
 */
qreal StyleHelper::dpiScaled(qreal value)
{
#ifdef Q_OS_MAC
  // mac系统dpi一直保持72
  return value;
#else
  return (value * my_window_scale_);
#endif
}

/**
 * @brief       根据dpi缩放控件大小
 * @param[in]   widget    控件
 */
void StyleHelper::sizeScaled(QWidget *widget)
{
#ifdef Q_OS_MAC
  return;
#else
  // 修改尺寸
  widget->resize(widget->width() * my_window_scale_, widget->height() * my_window_scale_);
  // 调整布局器的边距
  foreach (QLayout *layout, widget->findChildren<QLayout*>())
  {
    QMargins margins = layout->contentsMargins();
    margins.setBottom(margins.bottom() * my_window_scale_);
    margins.setTop(margins.top() * my_window_scale_);
    margins.setLeft(margins.left() * my_window_scale_);
    margins.setRight(margins.right() * my_window_scale_);
    layout->setContentsMargins(margins);
    layout->setSpacing(layout->spacing() * my_window_scale_);

    if (layout->inherits("QGridLayout"))
    {
      QGridLayout *grid_layout = qobject_cast<QGridLayout *>(layout);
      grid_layout->setHorizontalSpacing(grid_layout->horizontalSpacing() * my_window_scale_);
      grid_layout->setVerticalSpacing(grid_layout->verticalSpacing() * my_window_scale_);
    }
  }
#endif
}

使用api调整widget的尺寸

// 在页面的构造函数中调用
MyDialog::MyDialog(QWidget *parent) :
    QDialog(parent, Qt::MSWindowsFixedSizeDialogHint),
    ui(new Ui::MyDialog)
{
  ui->setupUi(this);
  // 适配分辨率大小
  StyleHelper::sizeScaled(this);
}

// 在一些设置大小的地方使用
ui->tool_button->setIconSize(QSize(StyleHelper::dpiScaled(24), StyleHelper::dpiScaled(24)));

3.3 qss尺寸问题

qss中尺寸使用的px单位,改为em使用。根据实际情况,可以灵活调整,共同使用px和em单位。

/* 对控件进行拉伸,使用了em单位 */
QMenu::item {
    min-width: 6.5em;
    min-height: 1.2em;
    background-color: transparent;
    margin: 0.1em;
    padding: 0em 0.5em 0em 0em;
}

/* 某些地方希望固定尺寸,不进行拉伸,则使用px单位 */
QToolButton {
  border: 1px solid #FFFFFF;
  border-radius: 0px;
  padding: 2px;
}

3.4 结论

以上3种方法组合使用,基本满足了大部分情况,若有哪里没实现到缩放的地方,可按照该思路一步一步解决。
该方案的效果还是比较符合预期,虽然实现起来比较繁琐复杂,所以能够在开发初期考虑到该问题,还是能够比较解决的。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【我和openGauss的故事】openGauss获奖项目讲解

文章目录前言参赛方案介绍系统需求分析主要功能模块设计思路字段基本数据分析页面及功能设计功能函数视图设计技术亮点及优势商业模式及市场前景功能测试项目总结前言 2022年8月30日华为鲲鹏应用大赛openGauss赛道上海赛区第三名获奖作品开源分享&#xff0c;我们团队参加本次…

再学C语言23:分支和跳转——if语句

一、简单if语句 if语句被称为分支语句&#xff08;branching statement&#xff09;或选择语句&#xff08;selection statement&#xff09;&#xff0c;功能是让程序选择分支中的一条前进 if语句一般形式&#xff1a; if(expression)statement 如果expression的值为真&am…

【数据结构】LeetCode移除链表元素、反转链表、链表的中间结点

目录 一、移除链表元素 1、题目说明 2、题目解析 二、反转链表 1、题目说明 2、题目解析 三、链表的中间结点 1、题目说明 2、题目解析 一、移除链表元素 1、题目说明 题目链接&#xff1a;移除链表的元素 给你一个链表的头节点 head &#xff0c;和一个整数 val&#xff0c;…

蓝牙资讯|苹果获得智能戒指专利,可用于交互 AR / VR 头显设备

美国商标和专利局&#xff08;USPTO&#xff09;批准并公示了苹果的一项智能戒指专利。这款戒指主要作为苹果混合现实头显设备的辅助交互设备&#xff0c;但可以和 iPhone、iPad、AirPods、Mac 和其它设备一起使用。 苹果希望通过智能戒指来改善 AR / VR 世界的交互体验&…

工程项目管理系统源码-简洁+好用+全面-工程项目管理系统

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 ​系统定义 工程项目管理企业不直接与该工程项目的总承…

javafx实现的工资管理系统

&#x1f345;程序员小王的博客&#xff1a;程序员小王的博客 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 如有编辑错误联系作者&#xff0c;如果有比较好的文章欢迎分享给我&#xff0c;我会取其精华去其糟粕 &#x1f345;java自学的学习…

ESP8266 SDK开发(ESP8266_RTOS_SDK 3.x)之AiThinkerIDE_V1.5.2安装、配置以及编写烧录一个程序

【本文发布于https://blog.csdn.net/Stack_/article/details/128509864&#xff0c;未经允许不得转载&#xff0c;转载须注明出处】 前言 乐鑫官方不搞IDE&#xff0c;安信可搞了IDE&#xff0c;但是各版本之间安装配置有差异&#xff0c;还没有文档说明。官方安装配置教程不完…

CTFHUB技能树-SSRF-redis协议踩坑

在gopherus上面输入命令&#xff1a;python gophers.py --exploit redis 将自动生成的代码url解密可以得到 如果是get传参需要再进行一次url编码 虽然蚁剑连接不上但可以用urlshell?cmdls / 获取flag 接下来看可以连接蚁剑的代码 文件名最好还是用shell.php 我测试了s.…

【C++初阶8-vector实现】没想的那么简单!

前言 本期带来vector实现&#xff0c;和以前的顺序表差别不大。 博主水平有限&#xff0c;不足之处望请斧正&#xff01; 预备知识 实现参考SGI的stl30 我们看这种源码&#xff0c;要抓框架看&#xff1a;首先找类&#xff0c;看它的属性&#xff0c;再看方法 template &l…

全方位解析 C 端和 B 端的产品特性

近年来&#xff0c;互联网进入下半场&#xff0c;C 端流量红利逐渐消退&#xff0c;很多企业转向了 B 端服务&#xff0c;随之而来的是产品设计者的转型&#xff0c;现在越来越多的 C 端产品设计师开始涉足到 B 端产品的设计&#xff0c;这是一个知识迁移的过程&#xff0c;需要…

自动驾驶专题介绍 ———— 摄像头

文章目录介绍工作原理实现功能分类按通信协议区分按不同感光芯片按像元排列方式介绍 摄像头可以采集汽车周边的图像信息&#xff0c;跟人类的眼睛最为接近。摄像头可以拥有较广的视场角、较大的分辨率&#xff0c;还可以提供颜色和纹理等信息。这些信息对于实现自动驾驶功能是存…

Mentor-dft 学习笔记 day48-OCC With Capture Enable Clock Control Operation Modes

OCC With Capture Enable 有一个OCC具有capture_enable输入&#xff0c;可以与自由运行的慢速时钟一起使用。当OCC指定为启用捕获&#xff08;capture_trigger:capture_en&#xff09;时&#xff0c;在输入自由运行的慢时钟上添加时钟门控器&#xff0c;以从自由运行的时钟输…

影响宝宝大脑发育的6个坏习惯,你可能每天都在做

“望子成龙&#xff0c;望女成凤”这几乎是每个父母的愿望。虽然有一个高智商的天才宝宝太难了&#xff0c;但从不妨碍父母希望孩子更健康、更聪明。所以大家都比较关注宝宝的大脑发育&#xff0c;希望宝宝的大脑发育更好&#xff0c;长大后更聪明。但在日常生活中&#xff0c;…

android 12+从后台启动FGS限制

后台启动FGS限制 限制简介 以 Android 12&#xff08;API 级别 31&#xff09;或更高版本为目标平台的应用在后台运行时无法启动前台服务&#xff0c;少数特殊情况除外。 如果应用程序在后台运行时尝试启动前台服务&#xff0c;而前台服务不满足其中一种异常情况&#xff0c;系…

vue前端打包Docker镜像并nginx运行

首先说明咱们的前端项目是基于Vue的&#xff0c;反向代理使用的是nginx 1.打包vue前端项目生成dist文件夹上传至服务器 新建一个文件夹&#xff0c;叫vueDockerTest&#xff0c;下面的文件都需要。 cert是你存放ssl证书的文件夹&#xff0c;nginx.conf 是nginx的配置文件&am…

Kotlin 惰性集合操作-序列 Sequence

集合操作函数 和 序列 在了解 Kotlin 惰性集合之前&#xff0c;先看一下 Koltin 标注库中的一些集合操作函数。 定义一个数据模型 Person 和 Book 类&#xff1a; data class Person(val name: String, val age: Int) data class Book(val title: String, val authors: List…

jmeter 5.5+influxdb 2.0+grafana v9.3.2 - 压测看板setup

Docker set up 安装docker应用 https://docs.docker.com/desktop/install/mac-install/&#xff0c;在官网下载docker安装包&#xff0c;和安装其他的mac应用是一样的操作。 设置国内的镜像仓库&#xff08;拉取镜像会快很多&#xff09; {"registry-mirrors": [&q…

叠氮-聚乙二醇-羧酸;叠氮-单乙二醇-丙酸Azido-PEG1-acid;1393330-34-1小分子PEG衍生物

Azido-PEG1-acid 中文名称&#xff1a;叠氮-聚乙二醇-羧酸&#xff1b;叠氮-单乙二醇-丙酸 英文名称&#xff1a;Azido-PEG1-acid&#xff1b; 分子式&#xff1a;C5H9N3O3 分子量 &#xff1a;159.1 CAS&#xff1a;1393330-34-1 外观&#xff1a;粘稠液体或者固体粉末&#…

SHA和AES加密+GUI Swing写的一个本地运行和保存的密码管理小工具

目录效果项目结构功能1、登录2、加密3、解密4、列表代码1、先准备好两种加密方式的工具类SHAUtilAESUtil2、登录窗口3、主页窗口&#xff08;加密和解密面板&#xff09;4、主页窗口&#xff08;列表面板&#xff09;5、主程序&#xff08;main&#xff09;最后通过SHA和AES加密…

TestStand-序列步骤属性

文章目录GeneralRun OptionLoopingPost ActionSwitchingSynchronizationExpressionPreconditionsRequirementAdditional ResultPropertyCtrl-N创建一个新的Sequence&#xff0c;通过右键创建任意步骤 General Name -步骤的名称。 Type -步骤类型。一般不需要设置。 Adapter-适…