Smooth Zoom In QGraphicsView: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
[[Category:HowTo]]<br />[[Category:Learning::Demos_and_Examples]]<br />[[Category:snippets]]
[[Category:HowTo]]
[[Category:Learning::Demos_and_Examples]]
[[Category:snippets]]


'''English''' [[Smooth_Zoom_In_QGraphicsView_Japanese|日本語]]
'''English''' [[Smooth_Zoom_In_QGraphicsView_Japanese|日本語]]
Line 7: Line 9:
A nice feature to a program with QGraphicsView is of course smooth zooming (like in Google Earth, for example). To achieve this we need to create our own widget inheriting QGraphicsView.
A nice feature to a program with QGraphicsView is of course smooth zooming (like in Google Earth, for example). To achieve this we need to create our own widget inheriting QGraphicsView.


The basic idea is to create new &quot;scaling action&amp;quot; every time user moves his mouse wheel by one &quot;step&amp;quot;. We will store the total number of scalings we have to do in _numScheduledScalings.
The basic idea is to create new "scaling action" every time user moves his mouse wheel by one "step". We will store the total number of scalings we have to do in _numScheduledScalings.


Of course, we need to reimplement the wheelEvent. First comes the code, then comes the explanation.
Of course, we need to reimplement the wheelEvent. First comes the code, then comes the explanation.


<code><br />void MyQGraphicsView::wheelEvent ( QWheelEvent * event )<br />{<br /> int numDegrees = event-&gt;delta() / 8;<br /> int numSteps = numDegrees / 15; // see QWheelEvent documentation<br /> _numScheduledScalings ''= numSteps;<br /> if (_numScheduledScalings * numSteps &lt; 0) // if user moved the wheel in another direction, we reset previously scheduled scalings<br /> _numScheduledScalings = numSteps;
<code>
<br /> QTimeLine *anim = new QTimeLine(350, this);<br /> anim-&gt;setUpdateInterval(20);
void MyQGraphicsView::wheelEvent ( QWheelEvent * event )
<br /> connect(anim, SIGNAL (valueChanged(qreal)), SLOT (scalingTime(qreal)));<br /> connect(anim, SIGNAL (finished()), SLOT (animFinished()));<br /> anim-&gt;start();<br />}<br /></code>
{
<br />After computing the &quot;intensity&amp;quot; of wheel move and adding it to _numScheduledScalings, we create a QTimeLine object that will invoke scalingTime() function every 20 ms during his 350ms lifespan.
int numDegrees = event->delta() / 8;
<br /><code><br />void MyQGraphicsView::scalingTime(qreal x)<br />{<br /> qreal factor = 1.0'' qreal(_numScheduledScalings) / 300.0;<br /> scale(factor, factor);<br />}<br /></code>
int numSteps = numDegrees / 15; // see QWheelEvent documentation
_numScheduledScalings ''= numSteps;
if (_numScheduledScalings * numSteps < 0) // if user moved the wheel in another direction, we reset previously scheduled scalings
_numScheduledScalings = numSteps;
 
QTimeLine *anim = new QTimeLine(350, this);
anim->setUpdateInterval(20);
 
connect(anim, SIGNAL (valueChanged(qreal)), SLOT (scalingTime(qreal)));
connect(anim, SIGNAL (finished()), SLOT (animFinished()));
anim->start();
}
</code>
 
After computing the "intensity" of wheel move and adding it to _numScheduledScalings, we create a QTimeLine object that will invoke scalingTime() function every 20 ms during his 350ms lifespan.
 
<code>
void MyQGraphicsView::scalingTime(qreal x)
{
qreal factor = 1.0'' qreal(_numScheduledScalings) / 300.0;
scale(factor, factor);
}
</code>


Factor depends on how much we want to zoom the scene. If user wants to zoom it just by a little bit, he will touch mousewheel very delicately. _numScheduledScalings will be small, and so will be factor. On the other hand if user will rotate the wheel intensively, _numScheduledScalings will be bigger, and so we will zoom the scene faster.
Factor depends on how much we want to zoom the scene. If user wants to zoom it just by a little bit, he will touch mousewheel very delicately. _numScheduledScalings will be small, and so will be factor. On the other hand if user will rotate the wheel intensively, _numScheduledScalings will be bigger, and so we will zoom the scene faster.


Of course, we need to take care of dynamically created QTimeLines:<br /><code><br />void MyQGraphicsView::animFinished()<br />{<br /> if (_numScheduledScalings &gt; 0)<br /> _numScheduledScalings—;<br /> else<br /> _numScheduledScalings++;<br /> sender()-&gt;~QObject();<br />}
Of course, we need to take care of dynamically created QTimeLines:
<code>
void MyQGraphicsView::animFinished()
{
if (_numScheduledScalings > 0)
_numScheduledScalings—;
else
_numScheduledScalings++;
sender()->~QObject();
}

Revision as of 09:41, 25 February 2015


English 日本語

Smooth Zoom In QGraphicsView

A nice feature to a program with QGraphicsView is of course smooth zooming (like in Google Earth, for example). To achieve this we need to create our own widget inheriting QGraphicsView.

The basic idea is to create new "scaling action" every time user moves his mouse wheel by one "step". We will store the total number of scalings we have to do in _numScheduledScalings.

Of course, we need to reimplement the wheelEvent. First comes the code, then comes the explanation.

void MyQGraphicsView::wheelEvent ( QWheelEvent * event )
{
 int numDegrees = event->delta() / 8;
 int numSteps = numDegrees / 15; // see QWheelEvent documentation
 _numScheduledScalings ''= numSteps;
 if (_numScheduledScalings * numSteps < 0) // if user moved the wheel in another direction, we reset previously scheduled scalings
 _numScheduledScalings = numSteps;

 QTimeLine *anim = new QTimeLine(350, this);
 anim->setUpdateInterval(20);

 connect(anim, SIGNAL (valueChanged(qreal)), SLOT (scalingTime(qreal)));
 connect(anim, SIGNAL (finished()), SLOT (animFinished()));
 anim->start();
}

After computing the "intensity" of wheel move and adding it to _numScheduledScalings, we create a QTimeLine object that will invoke scalingTime() function every 20 ms during his 350ms lifespan.

void MyQGraphicsView::scalingTime(qreal x)
{
 qreal factor = 1.0'' qreal(_numScheduledScalings) / 300.0;
 scale(factor, factor);
}

Factor depends on how much we want to zoom the scene. If user wants to zoom it just by a little bit, he will touch mousewheel very delicately. _numScheduledScalings will be small, and so will be factor. On the other hand if user will rotate the wheel intensively, _numScheduledScalings will be bigger, and so we will zoom the scene faster.

Of course, we need to take care of dynamically created QTimeLines: void MyQGraphicsView::animFinished() {

if (_numScheduledScalings > 0)
_numScheduledScalings—;
else
_numScheduledScalings++;
sender()->~QObject();

}