目录

Qt场景缩放踩坑记录,view缩放

目录

Qt——场景缩放踩坑记录,view缩放

在使用qt的场景进行图像的显示时需要缩放,这时负责缩放的是view,为了省事直接在widget中处理view没有进行重写。这时使用缩放就很容易产生一个问题,缩放后图像乱跑,我这里需要的是针对鼠标所在点的位置进行缩放。
查找资料以及自己各种踩坑代码之后,得到的结论,这个乱跑的现象与view和viewport有关,在这里你可以把它当做是两个东西,他们都有wheelEvent事件的处理,因为要在widget中处理view,必然要用eventFilter,但实际上我们要过滤的是viewport,因为我们在做缩放处理的时候使用的是viewport的坐标。如果过滤view,在进行完缩放后,图像还会发生一次移动,因为viewport中的wheelEvent事件还在正常执行,所以图像会漂移。只有过滤viewport才不会出现这个现象。

if (wheelEvent->delta() > 0)
{
				scale = 1.0 / 0.8;
}
else
{
				scale = 0.8;
}
//这里统计的是累计缩放,因为viewport是以累计缩放的形式进行缩放,所以要确定总倍数,可以用m11
//devicePixelRatioF这个是针对高倍率显示器的,一般情况下是1
auto m = m_View->transform().m11() / devicePixelRatioF() * scale;

//但有时在初始化时会做自适应的缩放,所以初始缩放不一定是1,这里如果要确定相对于初始状态缩放了多少
//还要记录一个初始缩放的状态

//之后就是采用变换的形式进行缩放
//因为场景的坐标是绝对的,view在变换时使用的是场景的坐标,所以要先得到鼠标位置对应的场景坐标
QPointF  mouseScene = m_View->mapToScene(wheelEvent->position().toPoint());
QTransform tr = m_View->transform();//获得当前的变换矩阵
//在当前矩阵的基础上进行变换,如果熟悉shader或者opengl的话,就会知道,缩放的步骤是
//缩放中心移动到原点->缩放->移动回去
//这里之所以是倒着写,是因为QTransform是右乘,m = m2*m1,先执行最右面,所以这里代码书写顺序时反着来
/* 以鼠标点为原点重新构造矩阵 */
tr.translate(mouseScene.x(), mouseScene.y())
				.scale(scale, scale)
				.translate(-mouseScene.x(), -mouseScene.y());

/* 应用 */
m_View->setTransform(tr);

这样可以实现以鼠标点位置的缩放,但是这里注意不要使用QGraphicsView::AnchorViewCenterQGraphicsView::AnchorUnderMouse,因为这里相当于我们自己处理了锚点,不需要再设置。