New mechanizm zooming QGraphicsView using mouse wheel.
--HG-- branch : develop
This commit is contained in:
parent
4e1742ded5
commit
35b3c654c6
|
@ -34,100 +34,63 @@
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include "../tools/vabstracttool.h"
|
#include "../tools/vabstracttool.h"
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <qmath.h>
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
GraphicsViewZoom::GraphicsViewZoom(QGraphicsView* view)
|
||||||
* @brief VMainGraphicsView constructor.
|
: QObject(view), _view(view), _numScheduledScalings(0)
|
||||||
* @param parent parent object.
|
|
||||||
*/
|
|
||||||
VMainGraphicsView::VMainGraphicsView(QWidget *parent)
|
|
||||||
:QGraphicsView(parent), _numScheduledScalings(0)
|
|
||||||
{
|
{
|
||||||
this->setResizeAnchor(QGraphicsView::AnchorUnderMouse);
|
_view->viewport()->installEventFilter(this);
|
||||||
this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
_view->setMouseTracking(true);
|
||||||
this->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
_modifiers = Qt::ControlModifier;
|
||||||
this->setInteractive(true);
|
_zoom_factor_base = 1.0015;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
void GraphicsViewZoom::gentle_zoom(double factor)
|
||||||
* @brief wheelEvent handle wheel events.
|
|
||||||
* @param event wheel event.
|
|
||||||
*/
|
|
||||||
//cppcheck-suppress unusedFunction
|
|
||||||
void VMainGraphicsView::wheelEvent(QWheelEvent *event)
|
|
||||||
{
|
{
|
||||||
int numSteps = event->delta() / 8 / 15; // see QWheelEvent documentation
|
_view->scale(factor, factor);
|
||||||
|
_view->centerOn(target_scene_pos);
|
||||||
_numScheduledScalings += numSteps;
|
QPointF delta_viewport_pos = target_viewport_pos - QPointF(_view->viewport()->width() / 2.0,
|
||||||
if (_numScheduledScalings * numSteps < 0)
|
_view->viewport()->height() / 2.0);
|
||||||
{ // if user moved the wheel in another direction, we reset
|
QPointF viewport_center = _view->mapFromScene(target_scene_pos) - delta_viewport_pos;
|
||||||
_numScheduledScalings = numSteps; // previously scheduled scalings
|
_view->centerOn(_view->mapToScene(viewport_center.toPoint()));
|
||||||
}
|
emit zoomed();
|
||||||
|
|
||||||
QTimeLine *anim = new QTimeLine(300, this);
|
|
||||||
anim->setUpdateInterval(20);
|
|
||||||
|
|
||||||
if (QApplication::keyboardModifiers() == Qt::ControlModifier)
|
|
||||||
{// If you press CTRL this code will be executed
|
|
||||||
connect(anim, &QTimeLine::valueChanged, this, &VMainGraphicsView::scalingTime);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
connect(anim, &QTimeLine::valueChanged, this, &VMainGraphicsView::scrollingTime);
|
|
||||||
}
|
|
||||||
connect(anim, &QTimeLine::finished, this, &VMainGraphicsView::animFinished);
|
|
||||||
anim->start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
void GraphicsViewZoom::set_modifiers(Qt::KeyboardModifiers modifiers)
|
||||||
* @brief scalingTime call each time when need handle scaling.
|
|
||||||
* @param x value from 0.0 to 1.0
|
|
||||||
*/
|
|
||||||
void VMainGraphicsView::scalingTime(qreal x)
|
|
||||||
{
|
{
|
||||||
Q_UNUSED(x);
|
_modifiers = modifiers;
|
||||||
const QPointF p0scene = mapToScene(mapFromGlobal(QCursor::pos()));
|
|
||||||
|
|
||||||
qreal factor = 1.0 + static_cast<qreal>(_numScheduledScalings) / 50.0;
|
|
||||||
scale(factor, factor);
|
|
||||||
|
|
||||||
const QPointF p1mouse = mapFromScene(p0scene);
|
|
||||||
const QPointF move = p1mouse - this->mapFromGlobal(QCursor::pos()); // The move
|
|
||||||
horizontalScrollBar()->setValue(static_cast<qint32>(move.x()) + horizontalScrollBar()->value());
|
|
||||||
verticalScrollBar()->setValue(static_cast<qint32>(move.y()) + verticalScrollBar()->value());
|
|
||||||
|
|
||||||
VAbstractTool::NewSceneRect(this->scene(), this);
|
|
||||||
|
|
||||||
emit NewFactor(factor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
void GraphicsViewZoom::set_zoom_factor_base(double value)
|
||||||
* @brief scrollingTime call each time when need handle scrolling.
|
{
|
||||||
* @param x value from 0.0 to 1.0
|
_zoom_factor_base = value;
|
||||||
*/
|
}
|
||||||
void VMainGraphicsView::scrollingTime(qreal x)
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void GraphicsViewZoom::scrollingTime(qreal x)
|
||||||
{
|
{
|
||||||
Q_UNUSED(x);
|
Q_UNUSED(x);
|
||||||
qreal factor = 1.0;
|
qreal factor = 1.0;
|
||||||
if (_numScheduledScalings < 0)
|
if (_numScheduledScalings < 0)
|
||||||
{
|
{
|
||||||
verticalScrollBar()->setValue(qRound(verticalScrollBar()->value() + factor*3.5));
|
factor = factor*2.8;
|
||||||
emit NewFactor(factor);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
verticalScrollBar()->setValue(qRound(verticalScrollBar()->value() - factor*3.5));
|
factor = factor*-2.8;
|
||||||
emit NewFactor(factor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_view->verticalScrollBar()->setValue(qRound(_view->verticalScrollBar()->value() + factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
void GraphicsViewZoom::animFinished()
|
||||||
* @brief animFinished
|
|
||||||
*/
|
|
||||||
void VMainGraphicsView::animFinished()
|
|
||||||
{
|
{
|
||||||
if (_numScheduledScalings > 0)
|
if (_numScheduledScalings > 0)
|
||||||
{
|
{
|
||||||
|
@ -140,6 +103,69 @@ void VMainGraphicsView::animFinished()
|
||||||
sender()->~QObject();
|
sender()->~QObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool GraphicsViewZoom::eventFilter(QObject *object, QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::MouseMove)
|
||||||
|
{
|
||||||
|
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
|
||||||
|
QPointF delta = target_viewport_pos - mouse_event->pos();
|
||||||
|
if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5)
|
||||||
|
{
|
||||||
|
target_viewport_pos = mouse_event->pos();
|
||||||
|
target_scene_pos = _view->mapToScene(mouse_event->pos());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event->type() == QEvent::Wheel)
|
||||||
|
{
|
||||||
|
QWheelEvent* wheel_event = static_cast<QWheelEvent*>(event);
|
||||||
|
if (QApplication::keyboardModifiers() == _modifiers)
|
||||||
|
{
|
||||||
|
if (wheel_event->orientation() == Qt::Vertical)
|
||||||
|
{
|
||||||
|
double angle = wheel_event->angleDelta().y();
|
||||||
|
double factor = qPow(_zoom_factor_base, angle);
|
||||||
|
gentle_zoom(factor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int numSteps = wheel_event->delta() / 8 / 15; // see QWheelEvent documentation
|
||||||
|
|
||||||
|
_numScheduledScalings += numSteps;
|
||||||
|
if (_numScheduledScalings * numSteps < 0)
|
||||||
|
{ // if user moved the wheel in another direction, we reset
|
||||||
|
_numScheduledScalings = numSteps; // previously scheduled scalings
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimeLine *anim = new QTimeLine(300, this);
|
||||||
|
anim->setUpdateInterval(20);
|
||||||
|
connect(anim, &QTimeLine::valueChanged, this, &GraphicsViewZoom::scrollingTime);
|
||||||
|
connect(anim, &QTimeLine::finished, this, &GraphicsViewZoom::animFinished);
|
||||||
|
anim->start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q_UNUSED(object)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief VMainGraphicsView constructor.
|
||||||
|
* @param parent parent object.
|
||||||
|
*/
|
||||||
|
VMainGraphicsView::VMainGraphicsView(QWidget *parent)
|
||||||
|
:QGraphicsView(parent), zoom(nullptr)
|
||||||
|
{
|
||||||
|
zoom = new GraphicsViewZoom(this);
|
||||||
|
this->setResizeAnchor(QGraphicsView::AnchorUnderMouse);
|
||||||
|
this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||||
|
this->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||||
|
this->setInteractive(true);
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VMainGraphicsView::ZoomIn()
|
void VMainGraphicsView::ZoomIn()
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,8 +29,65 @@
|
||||||
#ifndef VMAINGRAPHICSVIEW_H
|
#ifndef VMAINGRAPHICSVIEW_H
|
||||||
#define VMAINGRAPHICSVIEW_H
|
#define VMAINGRAPHICSVIEW_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This class adds ability to zoom QGraphicsView using mouse wheel. The point under cursor
|
||||||
|
* remains motionless while it's possible.
|
||||||
|
*
|
||||||
|
* Note that it becomes not possible when the scene's
|
||||||
|
* size is not large enough comparing to the viewport size. QGraphicsView centers the picture
|
||||||
|
* when it's smaller than the view. And QGraphicsView's scrolls boundaries don't allow to
|
||||||
|
* put any picture point at any viewport position.
|
||||||
|
*
|
||||||
|
* When the user starts scrolling, this class remembers original scene position and
|
||||||
|
* keeps it until scrolling is completed. It's better than getting original scene position at
|
||||||
|
* each scrolling step because that approach leads to position errors due to before-mentioned
|
||||||
|
* positioning restrictions.
|
||||||
|
*
|
||||||
|
* When zommed using scroll, this class emits zoomed() signal.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* new Graphics_view_zoom(view);
|
||||||
|
*
|
||||||
|
* The object will be deleted automatically when the view is deleted.
|
||||||
|
*
|
||||||
|
* You can set keyboard modifiers used for zooming using set_modified(). Zooming will be
|
||||||
|
* performed only on exact match of modifiers combination. The default modifier is Ctrl.
|
||||||
|
*
|
||||||
|
* You can change zoom velocity by calling set_zoom_factor_base().
|
||||||
|
* Zoom coefficient is calculated as zoom_factor_base^angle_delta
|
||||||
|
* (see QWheelEvent::angleDelta).
|
||||||
|
* The default zoom factor base is 1.0015.
|
||||||
|
*/
|
||||||
|
class GraphicsViewZoom : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
GraphicsViewZoom(QGraphicsView* view);
|
||||||
|
void gentle_zoom(double factor);
|
||||||
|
void set_modifiers(Qt::KeyboardModifiers modifiers);
|
||||||
|
void set_zoom_factor_base(double value);
|
||||||
|
signals:
|
||||||
|
void zoomed();
|
||||||
|
public slots:
|
||||||
|
void scrollingTime(qreal x);
|
||||||
|
void animFinished();
|
||||||
|
private:
|
||||||
|
QGraphicsView* _view;
|
||||||
|
Qt::KeyboardModifiers _modifiers;
|
||||||
|
double _zoom_factor_base;
|
||||||
|
QPointF target_scene_pos;
|
||||||
|
QPointF target_viewport_pos;
|
||||||
|
|
||||||
|
bool eventFilter(QObject* object, QEvent* event);
|
||||||
|
private:
|
||||||
|
/** @brief _numScheduledScalings keep number scheduled scalings. */
|
||||||
|
qint32 _numScheduledScalings;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The VMainGraphicsView class main scene view.
|
* @brief The VMainGraphicsView class main scene view.
|
||||||
*/
|
*/
|
||||||
|
@ -53,20 +110,15 @@ signals:
|
||||||
*/
|
*/
|
||||||
void MouseRelease();
|
void MouseRelease();
|
||||||
public slots:
|
public slots:
|
||||||
void scalingTime(qreal x);
|
|
||||||
void scrollingTime(qreal x);
|
|
||||||
void animFinished();
|
|
||||||
void ZoomIn();
|
void ZoomIn();
|
||||||
void ZoomOut();
|
void ZoomOut();
|
||||||
void ZoomOriginal();
|
void ZoomOriginal();
|
||||||
void ZoomFitBest();
|
void ZoomFitBest();
|
||||||
protected:
|
protected:
|
||||||
void wheelEvent ( QWheelEvent * event );
|
|
||||||
void mousePressEvent(QMouseEvent *mousePress);
|
void mousePressEvent(QMouseEvent *mousePress);
|
||||||
void mouseReleaseEvent(QMouseEvent *event);
|
void mouseReleaseEvent(QMouseEvent *event);
|
||||||
private:
|
private:
|
||||||
/** @brief _numScheduledScalings keep number scheduled scalings. */
|
GraphicsViewZoom* zoom;
|
||||||
qint32 _numScheduledScalings;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VMAINGRAPHICSVIEW_H
|
#endif // VMAINGRAPHICSVIEW_H
|
||||||
|
|
Loading…
Reference in New Issue
Block a user