QGraphicsView Zooming in and out under mouse position using mouse wheel finally

works like i want.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2015-12-02 20:39:25 +02:00
parent 8506afc056
commit 6cd674ec0f
2 changed files with 50 additions and 13 deletions

View File

@ -55,11 +55,20 @@ GraphicsViewZoom::GraphicsViewZoom(QGraphicsView* view)
void GraphicsViewZoom::gentle_zoom(double factor)
{
_view->scale(factor, factor);
if (factor < 1)
{
// Because 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 we will provide fictive scene size.
// Temporary and bigger than view, scene size will help position an image under cursor.
FictiveSceneRect(_view->scene(), _view);
}
_view->centerOn(target_scene_pos);
QPointF delta_viewport_pos = target_viewport_pos - QPointF(_view->viewport()->width() / 2.0,
_view->viewport()->height() / 2.0);
QPointF viewport_center = _view->mapFromScene(target_scene_pos) - delta_viewport_pos;
_view->centerOn(_view->mapToScene(viewport_center.toPoint()));
// In the end we just set correct scene size
VMainGraphicsView::NewSceneRect(_view->scene(), _view);
emit zoomed();
}
@ -112,8 +121,8 @@ void GraphicsViewZoom::animFinished()
* If don't do that we will zoom using old value cursor position on scene. It is not what we expect.
* Almoust the same we do in method GraphicsViewZoom::eventFilter.
*/
QPoint pos = _view->mapFromGlobal(QCursor::pos());
QPointF delta = target_scene_pos - _view->mapToScene(pos);
const QPoint pos = _view->mapFromGlobal(QCursor::pos());
const QPointF delta = target_scene_pos - _view->mapToScene(pos);
if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5)
{
target_viewport_pos = pos;
@ -173,6 +182,39 @@ bool GraphicsViewZoom::eventFilter(QObject *object, QEvent *event)
return false;
}
//---------------------------------------------------------------------------------------------------------------------
void GraphicsViewZoom::FictiveSceneRect(QGraphicsScene *sc, QGraphicsView *view)
{
SCASSERT(sc != nullptr);
SCASSERT(view != nullptr);
//Calculate view rect
//to receive the currently visible area, map the widgets bounds to the scene
const QPointF a = view->mapToScene(0, 0 );
const QPointF b = view->mapToScene(view->viewport()->width(), view->viewport()->height());
QRectF viewRect = QRectF( a, b );
//Calculate scene rect
const QRectF sceneRect = sc->sceneRect();
if (not sceneRect.contains(viewRect))
{//Scene less than view
//Scale view
QLineF topLeftRay(viewRect.center(), viewRect.topLeft());
topLeftRay.setLength(topLeftRay.length()*2);
QLineF bottomRightRay(viewRect.center(), viewRect.bottomRight());
bottomRightRay.setLength(bottomRightRay.length()*2);
viewRect = QRectF(topLeftRay.p2(), bottomRightRay.p2());
//Unite two rects
const QRectF newRect = sceneRect.united(viewRect);
sc->setSceneRect(newRect);
}
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VMainGraphicsView constructor.

View File

@ -36,11 +36,6 @@
* 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
@ -79,18 +74,18 @@ public slots:
void scrollingTime(qreal x);
void animFinished();
private:
Q_DISABLE_COPY(GraphicsViewZoom)
QGraphicsView* _view;
Qt::KeyboardModifiers _modifiers;
double _zoom_factor_base;
QPointF target_scene_pos;
QPointF target_viewport_pos;
QTimeLine *anim;
bool eventFilter(QObject* object, QEvent* event);
private:
Q_DISABLE_COPY(GraphicsViewZoom)
/** @brief _numScheduledScalings keep number scheduled scalings. */
qint32 _numScheduledScalings;
virtual bool eventFilter(QObject* object, QEvent* event) Q_DECL_OVERRIDE;
void FictiveSceneRect(QGraphicsScene *sc, QGraphicsView *view);
};
/**