QT解决因屏幕分辨率和缩放产生的界面异常(转载)

转载自:https://blog.csdn.net/qq_27450255/article/details/127262021

显示器分辨率和缩放比例

在某些情况下,由于屏幕分辨率和缩放比例不是100%,导致一些界面或字体的显示出现异常。此时需要获取到分辨率和缩放比例等相关参数,加以矫正,使界面在不同分辨率和缩放比例下都显示正常。
以Windows11为例,右键开始图标选择【系统】-【屏幕】,进入如下界面。
在这里插入图片描述
找到【缩放和布局】
在这里插入图片描述
此电脑的最佳缩放和显示器分辨率分别为200%,2560*1440;在此设置下可以达到最佳显示效果,但问题随之而来。

界面异常

正常情况,即100%缩放比例的情况下,一个图像显示窗口及字体如下,
在这里插入图片描述
现在将显示器分辨率和缩放比例调整到2560*1440和200%,同一个界面和字体如下
在这里插入图片描述
可以看到,图像显示窗口和字体都随之改变,字体变小,图像显示区则直接缩小了1倍,这些结果都能和显示器缩放比例对应上,我们现在知道,显示器缩放比例调整为原来的2倍,则界面显示区随之变为原来的0.5倍。
接下来就是如何通过QT获取到相关参数进而对相应窗口进行尺寸调整。

QT(6.2版本)获取主屏幕分辨率和缩放比例

细心的人可能注意到,第一张图上显示的是两个显示器,其中1为主显示器。直接上QT帮助文档。在帮助文档里找到QScreen Class。
在这里插入图片描述
找到其中几个接口:

 qreal devicePixelRatio() const
 qreal logicalDotsPerInch() const
 qreal logicalDotsPerInchX() const
 qreal logicalDotsPerInchY() const

其解释说说明如下,简单解释下:
在这里插入图片描述
此属性保存物理像素和设备无关像素之间的屏幕比率。主要看这句就行,

Common values are 1.0 on normal displays and 2.0 on "retina" displays. Higher values are also possible

正常情况下值为1,解释下"retina" displays。
用法我们后面说。
在这里插入图片描述
逻辑分辨率,和物理分辨率区分,物理分辨率我们用不到。所谓逻辑分辨率就是显示器每一英寸上的逻辑点数,就是我们常说的DPI。通常情况下XY方向值一样,平均值自然也一样。可根据实际情况选择使用。

该类通过静态接口函数获取

QScreen *screen = qApp->primaryScreen();

代码测试

下面进行无聊的测试环节。

QScreen *screen = qApp->primaryScreen();
qreal dpiVal = screen->logicalDotsPerInch();
qreal ratioVal = screen->devicePixelRatio();
qDebug() << dpiVal << ratioVal;

改个缩放值,运行一遍代码。
在这里插入图片描述
输出值如下:
在这里插入图片描述
规律很明显,稍微有点数学常识的人应该都可以总结出来,他们之间存在着线性关系,即

window缩放参数 / 100% = logicalDotsPerInch * devicePixelRatio / 96

实际应用

找到规律,就好办了,在使用的地方定义一个函数。

double SomeClass::GetScreenFactor()
{
    //获取屏幕缩放倍数
    QScreen *screen = qApp->primaryScreen();
    const int baseValue = 96;//100%时为96
    qreal dpiVal = screen->logicalDotsPerInch();
    qreal ratioVal = screen->devicePixelRatio();

    qDebug() << dpiVal << ratioVal;

    return dpiVal * ratioVal / baseValue;
}

具体哪里会用到就要根据自己的实际情况了,最常见的两个地方是

  • 界面构造或者初始化时
  • 界面尺寸改变时

以一段项目代码为例

//界面构造或者初始化时

auto factor = d->GetScreenFactor();
d->pHalconView = std::make_unique<HalconView>();
double iWindowWidth = ui->widget_view->width() * factor;
double iWindowHeight = ui->widget_view->height() * factor;
QPoint qPos = ui->widget_view->mapFromParent(QPoint(0, 0));
d->pHalconView->InitWindow(qPos.x(), qPos.y(), iWindowWidth, iWindowHeight, (void *)(ui->widget_view->winId()), strWindowName);
//重写resizeEvent
void SomeClass::resizeEvent(QResizeEvent *event)
{
	...
    auto factor = d->GetScreenFactor();
    d->pHalconView->ChangeWindowSize(0, 0, ui->widget_view->width() * factor, ui->widget_view->height() * factor);
	...
    QWidget::resizeEvent(event);
}

就是在原有数据的基础上乘以这个缩放因子。
结果就不一一展示了,在不同缩放比例下已经一样了。

在这里插入图片描述

需要说明下:这个常量DPI96在常见的显示器都是这个值,没有测试过所有显示器

多显示器
前面的方法是获取主显示器的参数值,多显示器情况下,也提供了接口

QList<QScreen *> QGuiApplication::screens()

这里就不赘述了

拓展

相信很多人都见过,一些应用程序在屏幕分辨率或缩放参数改变后或弹窗提示,以企业微信为例
在这里插入图片描述
这个也很简单,QScreen类有很多信号
在这里插入图片描述
只要绑定个槽函数,就能随时获取屏幕的参数变化,执行后续的操作,在线修改或者像企业微信那样做个提醒什么的,用法就很随意了。

QScreen *screen = qApp->primaryScreen();
connect(screen, &QScreen::logicalDotsPerInchChanged, [](double v){
    qDebug() << "new dpi " << v;
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值