PDA

View Full Version : How to zooming like in AutoCAD with QGraphicsView?



Tarhan
5th November 2010, 22:48
I want to change behaviour of QGraphicsView (in subclass) to enable zooming via overriding wheelEvent. I want to zoom like in AutoCAD, i.e. point in scene under mouse cursor same before and after zooming. Also when scene view resized, sceneRect remain same (but expanding if nessessary to keep original aspect ratio of scene).
I tried several math equations all of them works far for normal especially when scroll bars appears.
Please, give some code snippets and what else i need to override in subclass?

SixDegrees
5th November 2010, 23:05
One of the QGraphicsView tutorials has wheel zooming, along with the code. I don't recall which one, but it works fine for my purposes.

marcvanriet
6th November 2010, 22:50
header :


class CmwGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
explicit CmwGraphicsView(QWidget *parent = 0);

protected:
void wheelEvent(QWheelEvent *event);
void scaleView(qreal scaleFactor);

};


CPP :


CmwGraphicsView::CmwGraphicsView(QWidget *parent) :
QGraphicsView(parent)
{

}

void CmwGraphicsView::scaleView(qreal scaleFactor)
{
qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
if (factor < 0.07 || factor > 100)
return;

scale(scaleFactor, scaleFactor);
}

void CmwGraphicsView::wheelEvent(QWheelEvent *event)
{
scaleView(pow((double)2, -event->delta() / 240.0));
}

Of course this just zooms from the center of the view. You still have to work out zooming with the mouse pointer as center.

I would first translate to the mouse position, and then do the zooming.

Best regards,
Marc

ecanela
7th November 2010, 00:16
for zooming under the mouse cursor, use the function setResizeAnchor. this function set the possible anchors that QGraphicsView can use when the user resizes the view or when the view is transformed.
in this case use the AnchorUnderMouse enum value.




CmwGraphicsView::CmwGraphicsView(QWidget *parent) :
QGraphicsView(parent)
{
setResizeAnchor(QGraphicsView::AnchorUnderMouse); // anchir under the cursor
}

Tarhan
13th November 2010, 11:27
One of the QGraphicsView tutorials has wheel zooming, along with the code. I don't recall which one, but it works fine for my purposes.
Thanks, I found example you mentioned. In "Elastic Nodes" example used setTransformationAnchor(QGraphicsView::AnchorUnder Mouse). It works fine only when two scrollbars appears. But if only one scrollbar or no any scrollbars shown zooming under mouse cursor not working. I tried disable scrollbars (setting scrollbars' policy to Qt::ScrollBarAlwaysOff), result was same.
In my window constructor i'm creating view and setting scene rect (via QGraphicsView::setSceneRect(0,0,640,460) ).

for zooming under the mouse cursor, use the function setResizeAnchor. this function set the possible anchors that QGraphicsView can use when the user resizes the view or when the view is transformed.
in this case use the AnchorUnderMouse enum value.



CmwGraphicsView::CmwGraphicsView(QWidget *parent) :
QGraphicsView(parent)
{
setResizeAnchor(QGraphicsView::AnchorUnderMouse); // anchir under the cursor
}

I tried to execute setResizeAnchor alone and with setTransformationAnchor, result from adding setResizeAnchor nothing.

popper
17th January 2011, 08:16
Hi!
You should reimplement the QGraphicsView::wheelEvent ( QWheelEvent * event )
This code work fine.

header:


#include <QGraphicsView>

class GeoMapGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
GeoMapGraphicsView(QWidget *parent = 0);
void zoom(qreal factor, QPointF centerPoint);
protected:
void wheelEvent ( QWheelEvent * event );
private:
bool isTouched;
QPointF mousePos;

};


in source:



void GeoMapGraphicsView::wheelEvent ( QWheelEvent * e)
{
if (e->modifiers().testFlag(Qt::ControlModifier)){ // zoom only when CTRL key pressed
int numSteps = e->delta() / 15 / 8;

if (numSteps == 0) {
e->ignore();
return;
}
qreal sc = pow(1.25, numSteps); // I use scale factor 1.25
this->zoom(sc, mapToScene(e->pos()));
e->accept();
}
}

void GeoMapGraphicsView::zoom(qreal factor, QPointF centerPoint)
{
scale(factor, factor);
centerOn(centerPoint);
}