交互式QGraphicsView(平移缩放旋转)

xiaoxiao2021-02-28  50

Graphics View提供了一个平台,用于大量自定义 2D 图元的管理与交互,框架包括一个事件传播架构,支持场景 Scene 中的图元 Item 进行精确的双精度交互功能。Item 可以处理键盘事件、鼠标按下、移动、释放和双击事件,同时也能跟踪鼠标移动。

和 Google 地图一样,在管理大量 Item 的时候,通常需要 View 具有交互(平移/缩放/旋转)功能。

简述交互式 QGraphicsView 效果源码

交互式 QGraphicsView

便于以后复用,实现一个交互式 QGraphicsView - InteractiveView。

主要功能包括:

平移:  方式一:鼠标左键按下,然后移动方式二:按下上/下/左/右键分别向各个方向移动 缩放:  方式一:鼠标滚轮向上滚动放大,向下滚动缩小方式二:按加号键(带 Shift)进行放大,按减号键缩小 旋转:按空格键逆时针旋转,回车键顺时针旋转

效果

源码

interactive_view.h

#ifndef INTERACTIVE_VIEW_H #define INTERACTIVE_VIEW_H #include <QGraphicsView> class QWheelEvent; class QKeyEvent; class InteractiveView : public QGraphicsView { Q_OBJECT public: explicit InteractiveView(QWidget *parent = 0); // 平移速度 void setTranslateSpeed(qreal speed); qreal translateSpeed() const; // 缩放的增量 void setZoomDelta(qreal delta); qreal zoomDelta() const; protected: // 上/下/左/右键向各个方向移动、加/减键进行缩放、空格/回车键旋转 void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; // 平移 void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; // 放大/缩小 void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; public Q_SLOTS: void zoomIn(); // 放大 void zoomOut(); // 缩小 void zoom(float scaleFactor); // 缩放 - scaleFactor:缩放的比例因子 void translate(QPointF delta); // 平移 private: Qt::MouseButton m_translateButton; // 平移按钮 qreal m_translateSpeed; // 平移速度 qreal m_zoomDelta; // 缩放的增量 bool m_bMouseTranslate; // 平移标识 QPoint m_lastMousePos; // 鼠标最后按下的位置 qreal m_scale; // 缩放值 }; #endif // INTERACTIVE_VIEW_H 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748

平移速度默认为 1.0,可以使用 setTranslateSpeed() 来改变。缩放的增量大小也可以使用 setZoomDelta() 改变。

interactive_view.cpp

#include <QWheelEvent> #include <QKeyEvent> #include "interactive_view.h" #define VIEW_CENTER viewport()->rect().center() #define VIEW_WIDTH viewport()->rect().width() #define VIEW_HEIGHT viewport()->rect().height() InteractiveView::InteractiveView(QWidget *parent) : QGraphicsView(parent), m_translateButton(Qt::LeftButton), m_scale(1.0), m_zoomDelta(0.1), m_translateSpeed(1.0), m_bMouseTranslate(false) { // 去掉滚动条 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setCursor(Qt::PointingHandCursor); setRenderHint(QPainter::Antialiasing); setSceneRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX); centerOn(0, 0); } // 平移速度 void InteractiveView::setTranslateSpeed(qreal speed) { // 建议速度范围 Q_ASSERT_X(speed >= 0.0 && speed <= 2.0, "InteractiveView::setTranslateSpeed", "Speed should be in range [0.0, 2.0]."); m_translateSpeed = speed; } qreal InteractiveView::translateSpeed() const { return m_translateSpeed; } // 缩放的增量 void InteractiveView::setZoomDelta(qreal delta) { // 建议增量范围 Q_ASSERT_X(delta >= 0.0 && delta <= 1.0, "InteractiveView::setZoomDelta", "Delta should be in range [0.0, 1.0]."); m_zoomDelta = delta; } qreal InteractiveView::zoomDelta() const { return m_zoomDelta; } // 上/下/左/右键向各个方向移动、加/减键进行缩放、空格/回车键旋转 void InteractiveView::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Up: translate(QPointF(0, -2)); // 上移 break; case Qt::Key_Down: translate(QPointF(0, 2)); // 下移 break; case Qt::Key_Left: translate(QPointF(-2, 0)); // 左移 break; case Qt::Key_Right: translate(QPointF(2, 0)); // 右移 break; case Qt::Key_Plus: // 放大 zoomIn(); break; case Qt::Key_Minus: // 缩小 zoomOut(); break; case Qt::Key_Space: // 逆时针旋转 rotate(-5); break; case Qt::Key_Enter: // 顺时针旋转 case Qt::Key_Return: rotate(5); break; default: QGraphicsView::keyPressEvent(event); } } // 平移 void InteractiveView::mouseMoveEvent(QMouseEvent *event) { if (m_bMouseTranslate){ QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_lastMousePos); translate(mouseDelta); } m_lastMousePos = event->pos(); QGraphicsView::mouseMoveEvent(event); } void InteractiveView::mousePressEvent(QMouseEvent *event) { if (event->button() == m_translateButton) { // 当光标底下没有 item 时,才能移动 QPointF point = mapToScene(event->pos()); if (scene()->itemAt(point, transform()) == NULL) { m_bMouseTranslate = true; m_lastMousePos = event->pos(); } } QGraphicsView::mousePressEvent(event); } void InteractiveView::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == m_translateButton) m_bMouseTranslate = false; QGraphicsView::mouseReleaseEvent(event); } // 放大/缩小 void InteractiveView::wheelEvent(QWheelEvent *event) { // 滚轮的滚动量 QPoint scrollAmount = event->angleDelta(); // 正值表示滚轮远离使用者(放大),负值表示朝向使用者(缩小) scrollAmount.y() > 0 ? zoomIn() : zoomOut(); } // 放大 void InteractiveView::zoomIn() { zoom(1 + m_zoomDelta); } // 缩小 void InteractiveView::zoomOut() { zoom(1 - m_zoomDelta); } // 缩放 - scaleFactor:缩放的比例因子 void InteractiveView::zoom(float scaleFactor) { // 防止过小或过大 qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); if (factor < 0.07 || factor > 100) return; scale(scaleFactor, scaleFactor); m_scale *= scaleFactor; } // 平移 void InteractiveView::translate(QPointF delta) { // 根据当前 zoom 缩放平移数 delta *= m_scale; delta *= m_translateSpeed; // view 根据鼠标下的点作为锚点来定位 scene setTransformationAnchor(QGraphicsView::AnchorUnderMouse); QPoint newCenter(VIEW_WIDTH / 2 - delta.x(), VIEW_HEIGHT / 2 - delta.y()); centerOn(mapToScene(newCenter)); // scene 在 view 的中心点作为锚点 setTransformationAnchor(QGraphicsView::AnchorViewCenter); } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171

这里,主要重写了键盘及鼠标事件,具体说明请参考注释!

http://blog.csdn.net/liang19890820/article/details/53543017

转载请注明原文地址: https://www.6miu.com/read-57478.html

最新回复(0)