简述
转:http://blog.csdn.net/liang19890820
Graphics View提供了一个平台,用于大量自定义 2D 图元的管理与交互,框架包括一个事件传播架构,支持场景 Scene 中的图元 Item 进行精确的双精度交互功能。Item 可以处理键盘事件、鼠标按下、移动、释放和双击事件,同时也能跟踪鼠标移动。
和 Google 地图一样,在管理大量 Item 的时候,通常需要 View 具有交互(平移/缩放/旋转)功能。
交互式 QGraphicsView
便于以后复用,实现一个交互式 QGraphicsView - InteractiveView。
主要功能包括:
- 平移:
- 方式一:鼠标左键按下,然后移动
- 方式二:按下上/下/左/右键分别向各个方向移动
- 缩放:
- 方式一:鼠标滚轮向上滚动放大,向下滚动缩小
- 方式二:按加号键(带 Shift)进行放大,按减号键缩小
- 旋转:按空格键逆时针旋转,回车键顺时针旋转
效果
![这里写图片描述](http://img.blog.csdn.net/20161209185920212?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTAxMjkzMg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
源码
interactive_view.h
#ifndef INTERACTIVE_VIEW_H#define INTERACTIVE_VIEW_H#include <QGraphicsView>class QWheelEvent;class QKeyEvent;class InteractiveView : public QGraphicsView{ Q_OBJECTpublic: 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); 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
平移速度默认为 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) { 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);}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){ delta *= m_scale; delta *= m_translateSpeed; setTransformationAnchor(QGraphicsView::AnchorUnderMouse); QPoint newCenter(VIEW_WIDTH / 2 - delta.x(), VIEW_HEIGHT / 2 - delta.y()); centerOn(mapToScene(newCenter)); setTransformationAnchor(QGraphicsView::AnchorViewCenter);
}