简述
Graphics View提供了一个平台,用于大量自定义 2D 图元的管理与交互,框架包括一个事件传播架构,支持场景 Scene 中的图元 Item 进行精确的双精度交互功能。Item 可以处理键盘事件、鼠标按下、移动、释放和双击事件,同时也能跟踪鼠标移动。
和 Google 地图一样,在管理大量 Item 的时候,通常需要 View 具有交互(平移/缩放/旋转)功能。
交互式 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);
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 );
}