在我的上一篇博客中,我们谈到了对场景中图元的平移,旋转和缩放的操作,在这篇博客中,我将会继续介绍,对视口view的操作。
上一篇博客:QGraphicsView框架下,图元的操作(缩放,平移,旋转):
https://blog.csdn.net/EddyXie/article/details/91489519
1. 缩放操作
QGraphicsView的缩放,调用自身的void QGraphicsView::scale(qreal sx, qreal sy),传参为X和Y两个方向的缩放比,换而言之,view的缩放,能够支持拉长,或拉扁的操作,这里我演示一段代码,通过继承QGraphicsView类,重新实现鼠标滚轮方法,再调用自己的缩放功能函数:
//鼠标滚轮事件
void MyGraphicsView::wheelEvent(QWheelEvent* event) {
int numValue = event->delta(); //获取事件中滚轮的步进距离
qreal numDegrees = numValue / 8.0;
qreal numSteps = numDegrees / 15.0;
this->MyScale(numSteps); //调用缩放接口
}
//自定义的view缩放方法
void MyGraphicsView::MyScale(qreal step) {
qreal factor = 1.0 + step / 500.0;
this->zoom *= factor;//zoom为类中私有成员变量,用于记录对象的当前的缩放比
if (this->zoom < 0.01) return;
this->scale(factor, factor);
}
2.平移操作
QGraphicsView的平移,是通过调用自身的void QGraphicsView::centerOn(qreal x, qreal y),传参为场景Scene的坐标系,该方法的将view对场景的观测中心移动到指定的值上,其中相对复杂的是,为了保证平移之后,再进行缩放的正确性,需要在每次平移先后定立锚点,在这里给出一个实例代码,同样为继承QGraphicsView对象,重载了鼠标平移事件,并在事件中,调用自己的平移方法:
//鼠标平移事件
void MyGraphicsView::mouseMoveEvent(QMouseEvent* event) {
//获取每次鼠标在场景坐标系下的平移量
QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(this->lastMousePos);
//调用平移方法
this->MyMove(mouseDelta);
//lastMousePos是MyGraphicsView的私有成员变量,用以记录每次的事件结束时候的鼠标位置
this->lastMousePos = event->pos();
}
//自定义的平移方法
void MyGraphicsView::MyMove(QPointF delta) {
//如果是在缩放之后,调用的平移方法,那么平移量先要乘上缩放比,transform是view的变换矩阵,m11可以用为缩放比
delta *= this->transform().m11();
//修改锚点,调用缩放方法
this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
this->centerOn(this->mapToScene(QPoint(this->viewport()->rect().width()/ 2 - delta.x(),
this->viewport()->rect().height()/ 2 - delta.y())));
this->setTransformationAnchor(QGraphicsView::AnchorViewCenter);
}
在写这段代码的时候,我曾经犯了个错误,调用centerOn的时候,一开始写为:
this->centerOn(this->mapToScene(QPoint(this->rect().width()/ 2 - delta.x(), this->rect().height()/ 2 - delta.y())));
即每次通过view在UI中窗口的中心坐标,再来换算Scene场景中对应的坐标,但是代码运行得到的结果是,每次鼠标拖拽,场景都往反方向跑,在查阅了手册后,发现原来如果调用view自己的mapToScene,需要传入view的坐标系,而非窗口坐标系,两者并不是同一会事。
3.旋转操作
QGraphicsView的旋转操作,使用的是void QGraphicsView::rotate(qreal angle)方法,传参是旋转的角度值
当然,上述都是一些显式的方法,如果大家对矩阵图像操作比较数量,上述的方法都可以使用矩阵完成:
QMatrix matrix;
matrix.scale(scale, scale);
matrix.rotate(rotateSlider->value());
graphicsView->setMatrix(matrix);