QWindow类devicePixelRatio函数作用

在实际开发中,我们经常看到如下代码段:

void QtWidgetsApplication1::copyWnd()
{
    qreal dpr = window()->windowHandle()->devicePixelRatio();
    QPixmap pixmap(this->size() * dpr);
    pixmap.setDevicePixelRatio(dpr);

     ...... // 其它代码
}

其中QtWidgetsApplication1为QtWidgets的子类。这里的devicePixelRatio()函数有什么作用呢?

先摘录一个来自知乎网友提供的一个例子:

作者:暮成雪
链接:https://www.zhihu.com/question/40506180/answer/623203881
来源:知乎

我们以mac的发展史来说明什么是物理分辨率,以及为什么需要衍生出逻辑分辨率。

我们的主人公是乔帮主和比尔盖茨。此时乔帮主面前有一台mac,屏幕的分辨率是1280*720,这就是物理分辨率。乔帮主对比尔盖茨说,给我的mac开发一个word软件吧。盖茨说OK,于是写了一个软件,这个软件显示的时候长度是1280像素,宽度是720像素,正好能够盖满整个mac屏幕。乔帮主看了之后很满意。

有一天,乔帮主看自己的mac屏幕觉得很粗糙,一点都不清晰锐利。于是聪明的乔帮主想到,同样是15寸的屏幕,我把像素点翻倍,不就可以更清晰了吗?于是他把mac的物理分辨率改成了2560*1440的分辨率,相当于每个像素点的尺寸减少了4倍(保持原来每个像素占据的面积不变,放了4个像素,这每个像素占据的面积是原来像素占据面积的1/4),这下再也看不出颗粒感了,乔帮主很满意。但是,当乔帮主打开盖茨给他写的word的时候,傻眼了,原本全屏的word现在只占屏幕的四分之一,而且文字非常的小。乔帮主打电话给盖茨说,你的软件怎么出问题了?盖茨回答说,我开发的时候你的mac分辨率就是1280*720,你自己改了硬件尺寸怪我咯,我很忙没空给你改软件代码,你就凑合着用吧。乔帮主稍作思考,马上想出了一个非常聪明的主意!他在软件和硬件之间的系统层加了一层逻辑分辨率。虽然屏幕横向有2560个像素点,但是告诉软件我只有1280个像素点!当word的宽度要占1280个像素的时候,实际上已经占了2560个像素。于是我们的word又占满屏幕了!于是乔帮主把这个机智的想法命名为逻辑分辨率,不管我显示器的硬件有多少个像素点,我只会告诉软件我的逻辑分辨率,这样软件的代码就不用修改也能在不同的屏幕上显示效果一致。在多年后,mac的物理分辨率已经达到了5120 x 2880,但是告诉软件的时候还是说我的分辨率1280*720,相当在盖茨看来的一个逻辑像素点,背后实际上已经有16个物理像素点为其工作了!

 物理像素与逻辑像素相关概念:

关键词:

  物理像素pp(physical pixel)

  逻辑像素/设备独立像素dip(Device Independent Pixels)

  设备像素比dpr(Device Pixel Ratio)

  每英寸像素数ppi(pixel per inch)

  每英寸点数dpi (Dots Per Inch)

       像素密度pd(Pixel  density)

(1)物理像素(physical pixel)
        物理像素又被称为设备像素(pp),他是显示设备中一个最微小的物理部件。一个设备的物理像素是固定不变的。见过街上那些走红字的 LED 显示屏么?上面的那一颗颗的 LED 灯就是这块屏幕的发光点,一块LED显示屏宽高有几寸是在生产的时候就被定好的,而宽高各能容纳下多少颗像素,也是在生产的时候就被定好的,这就是我们说的物理像素。每个像素可以根据操作系统设置自己的颜色和亮度。

        所谓的一倍屏、二倍屏(Retina)、三倍屏,指的是设备以多少物理像素来显示一个CSS像素,也就是说,多倍屏以更多更精细的物理像素点来显示一个CSS像素点,在普通屏幕下1个CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素。

(2)CSS像素/逻辑像素/设备独立像素/设备无关像素(Device Independent Pixels)

        这几个像素的名称其实是指同一个概念,设备独立像素(又称设备无关像素 Device Independent Pixels),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素,Qt界面中的像素),然后由相关系统转换为物理像素。

 (3)设备像素比(Device Pixel Ratio, DPR):一个设备的物理像素与逻辑像素之比

设备像素比 (dpr)= 物理像素(pp) / 设备独立像素(dip)

       在Retina屏的iphone上,devicePixelRatio的值为2,也就是说1个css像素相当于2个物理像素。通常所说的二倍屏(retina)的dpr是2, 三倍屏是3。  该值也是QWindow类devicePixelRatio函数返回的值。

  (4)每英寸像素数ppi(pixel per inch)

       就是每1英寸有多少个像素。px就是表示pixel,像素是屏幕上显示数据的最基本的点。px是一个点,它不是自然界的长度单位,谁能说出一个“点”有多长多大么?可以画的很小,也可以很大。如果点很小,那画面就清晰,我们称它为“分辨率高”,反之,就是“分辨率低”。所以,“点”的大小是会“变”的,也称为“相对长度”。在计算机窗体、图像、页面等呈现给对象中,所有的“大”“小”概念,都是基于“屏幕”这个“界面”上。“屏幕”上的各种信息,包括文字、图片、表格等等,都会随屏幕的分辨率变化而变化,一个100px宽度大小的图片,在800×600分辨率下,要占屏幕宽度的1/8,但在1024×768下,则只占约1/10。所以如果在定义字体大小时,使用px作为单位,那一旦用户改变显示器分辨率从800到1024,用户实际看到的文字就要变“小”(自然长度单位),甚至会看不清,影响浏览。

  (5)每英寸点数dpi(dots per inch)

pt就是point,是印刷行业常用单位,等于1/72英寸。因此就有这样的说法,pixel是相对大小,而point是绝对大小。在Windows里,默认显示设置中,把文字定义为96DPI,即每英寸 96个点。(微软都将DPI和PPI混为一体,我们也就无须较真了)。这样的定义,说明了:1px=1/96英寸。联系pt的概念,1pt=1/72英寸,可以得出,在这样的设置中,1px=0.75pt,常见的宋体9pt=12px。在显示器分辨率不变的基础上(比如现在常用的1024×768),1px大小也就固定不变,改变显示设置,调整为144DPI,可以得出,1px=0.5pt,常见的宋体9pt=18px。原先用12px来组成的一个文字,现在需要18px来组成,px多了,文字就“大”了,更易阅读了。所以,px和pt的使用区别,只有当用户改变默认的96DPI下才会产生:使用px定义文字,无论用户怎么设置,都不会改变大小;使用pt定义文字,当用户设置超过96DPI的值,数值越大,字体就越大。

 (6) 像素密度pd(Pixel  density)

    屏幕像素密度(pd)是指一个设备表面上存在的像素数量,它通常以每英寸有多少像素(ppi)或每英寸多个点(dpi)来衡量的。屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。

屏幕像素密度(ppi) = 对角线分辨率 / 对角线尺寸

我们平时所说的屏幕尺寸一般是指屏幕对角线的尺寸,而不是指屏幕的长或高。

代码分析:

通过前文的描述,前面代码:

第3行:返回显示器像素(物理像素)和窗体像素(逻辑像素)的比值dpr。即用dpr个物理像素点绘制Qt窗体中的1个像素点,dpr在默认情况下为1,只有在高清屏才会大于1。本句代码中的window()返回本窗体的QWindow对象,而window()->windowHandle()则返回QWindow对象的native widget对象。关于QWidget的parentWidget、window、nativeParent窗体的概念及用法,请参考:《QWidget的parentWidget、window、nativeParentWidget区别与理解》。

第4行:QPixmap类对象pixmap设置其尺寸为当前窗体尺寸的dpr倍,按理说此时pixmap会比窗体尺寸大dpr倍,但实际不是这样。这是因为Qt内部的基于QPixmap类的布局器在计算布局时会将dpr考虑进来,从而导致pixmap几何布局按下面公式计算:

layoutSize = pixmap.size() / pixmap.devicePixelRatio()

       即还是原来的没有乘以dpr的大小。也就是说这么多物理像素还是得在原来pixmap尺寸大小的地方显示,假如dpr大于1,则必然在pixmap原来只显示1个像素的地方要显示dpr个像素,这样会导致pixmap显示更高清,因为原来1个像素占据的地方被dpr个像素占据显示了,这就是Qt实现高清屏采用的技术。

总结:

  • devicePixelRatio函数获取高清屏下每个逻辑像素对应几个物理像素,即绘制一个逻辑像素需要用到几个物理像素。
  • 诸如setDevicePixelRatio之类的函数,就是告知QPainters对象,在被绘制的目标上用几个物理像素来绘制1个逻辑像素。

参考链接:

【1】:https://www.zhihu.com/question/40506180/answer/623203881

【2】:物理像素与逻辑像素相关概念 - 剑仙6 - 博客园 (cnblogs.com)

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值