适配高DPI QWidget::move移动有错误?
创始人
2024-03-05 00:35:31
0

适配高DPI QWidget::move移动有错误?

在这里插入图片描述

1、现象

在适配高DPI文章发布之后,有个小伙伴立马联系我说增加了这个特性之后,发现一个移动坐标的问题。

比如说:QWidget::move(500, 500),在实际的高DPI屏幕上移动的像素并不是QPoint(500, 500),而是比QPoint(500, 500)要大。

我觉得挺有意思,立马就写个demo测试下,果然如他所说的。

同理我测试了QWidget::setGeometry()也是这样的。

这个现象还是挺奇怪的,让我们一探究竟。

2、解决方法

老规矩,我先说下解决方案。在编译的时候可能会报错,你需要在你的vs中添加头文件目录

在这里插入图片描述

#include BOOL g_RecalcPoint(QWidget *widget, const QRect &oldRect, QPoint &point)
{if (nullptr == widget || nullptr == widget->windowHandle()){return FALSE;}// 获取到缩放之后的坐标QRect screenAboutRect = QHighDpi::toNativePixels(oldRect, widget->windowHandle()->screen());// 获取缩放比例QHighDpiScaling::ScaleAndOrigin scale = QHighDpiScaling::scaleAndOrigin(widget->windowHandle()->screen());// 目标点QPoint x1 = QPoint(oldRect.x(), oldRect.y());QPoint x2 = QPoint(screenAboutRect.x(), screenAboutRect.y());if (0 == scale.factor)scale.factor = 1.0;// 缩放公式逆推QPoint x3 = ((scale.factor+1)*x1 - x2)/scale.factor;point = x3;return TRUE;
}//计算高度
BOOL g_RecalcRect(QWidget *widget, const QRect &oldRect, QRect &newRect, bool updateWidget, bool updateHeight)
{if (nullptr == widget || nullptr == widget->windowHandle()){return FALSE;}newRect = oldRect;QHighDpiScaling::ScaleAndOrigin scale = QHighDpiScaling::scaleAndOrigin(widget->windowHandle()->screen());if (updateWidget){newRect.setWidth(oldRect.width()/scale.factor);}if (updateHeight){newRect.setHeight(oldRect.height()/scale.factor);}return TRUE;
}

3、原理解释

3.1公式解释

x1就是我们需要移动到的点(目标),x2就是经过了缩放的点,factor就是缩放因子。但是我们现在的目标是x1,也就是要有个点x3经过同样的缩放要能达到x1位置。本质上我就是把原来的缩放公式进行了逆推。x_1 就是我们需要移动到的点(目标),x_2就是经过了缩放的点,factor就是缩放因子。\\ 但是我们现在的目标是x_1,也就是要有个点x_3经过同样的缩放要能达到x_1位置。\\ 本质上我就是把原来的缩放公式进行了逆推。 x1​就是我们需要移动到的点(目标),x2​就是经过了缩放的点,factor就是缩放因子。但是我们现在的目标是x1​,也就是要有个点x3​经过同样的缩放要能达到x1​位置。本质上我就是把原来的缩放公式进行了逆推。

{(x1−y)×factor+y=x2(x3−y)×factor+y=x1\begin{cases} (x_1-y) \times factor + y = x_2\\ (x_3-y) \times factor + y = x1 \end{cases} {(x1​−y)×factor+y=x2​(x3​−y)×factor+y=x1​

解方程组得出如下的公式,就是上面的公式由来。
x3=((1+factor)×x1−x2)factorx_3 = ((1+factor) \times x_1 - x_2) \over factor factorx3​=((1+factor)×x1​−x2​)​

还有一个疑问:缩放公式我是怎么来的?

除了看源代码,没有技巧可言。

我把代码贴出来给你看下就知道了。这里的origin其实就是上面方程组的y,其实这个参数不重要,因为最后被消除掉了。

inline QPoint scale(const QPoint &pos, qreal scaleFactor, QPoint origin = QPoint(0, 0))
{return (pos - origin) * scaleFactor + origin;
}

再提一句,为什么在g_RecalcRect中计算高度和宽度的需要oldRect.height()/scale.factor,也是根据源码的公式逆推的。

最有一个问题:我怎么就找到这里了呢?

看代码分析流程,再加上调试手段,就会定位到这里了。我把调用堆栈截图你看下就明白了。注意我这里给的QWidget::setGeometry()流程,其实QWidget::move()也是会调用QWidget::setGeometry()

在这里插入图片描述

4、总结

从现象来看是很奇怪,但是我们一旦知道原理之后,就发现这一切理所当然的。

需要深究原理,不能有懈怠之心。谜题总是会解开的。

相关内容

热门资讯

三部门部署开展“法援志愿行”活... 新华社北京12月23日电(记者齐琪)记者12月23日从司法部获悉,司法部、教育部、共青团中央印发通知...
莆田12岁女孩被虐死案生父改判... 福建省高院此前对莆田12岁女孩被虐死案作出二审判决,维持了对继母许金花的死刑判决。而对于被害女孩的生...
原创 丰... 丰臣秀吉生前创立的五大老·五奉行体制一直是学界研究的热点。通常认为,五大老是在秀吉去世后,成为丰臣政...
李营营律师:员工利用仿冒手段“... 人民法院案例库:员工利用仿冒手段“飞单”,行为性质如何认定? 手段行为分别构成侵害商标权、侵害企业名...
男子长期偷窥女室友,把摄像头装... 一个安全的居住空间对每个人意味着什么?它不仅是遮风挡雨的居所,更是城市给予奋斗者最基本的尊严与保障。...
多位作家发起版权诉讼,指控六大... 【环球网科技综合报道】12月23日消息,据彭博社报道,一场版权诉讼在美国科技与文学领域掀起波澜。包括...
因纠纷残杀幼童 行凶者一审被判... 2025年12月23日,广东省湛江市中级人民法院一审公开宣判被告人易庚华故意杀人案,以故意杀人罪判处...
新修订《治安管理处罚法》规定“... 极目新闻记者 邓波 2026年1月1日起,新修订的《中华人民共和国治安管理处罚法》将正式施行,其中第...
住房城乡建设部:加快构建房地产... 记者今日从住房城乡建设部获悉,12月22日至23日,全国住房城乡建设工作会议在北京召开。会议全面盘点...
OpenAI等六大AI巨头遭作... 界面新闻记者 | 宋佳楠 当地时间12月22日,两届普利策新闻奖得主约翰·卡雷鲁牵头的作家群体,向...