1
votes

I use a QPropertyAnimation to animate user input to navigate in a widget. Namely, I use it to smooth zooming using the mouse wheel.

Currently, when the user gives a new input (rotates the mouse wheel), the current animation gets canceled and a new animation starts, beginning with the current value of my zoom property.

For example, if a zoom-in operation scales the view by factor 2, we can imagine the following scenarios:

   User input         |  Zoom before the animation  |  Animation's end value
----------------------+-----------------------------+--------------------------
   Mouse wheel up     |                      100 %  |                  200 %
   (wait)             |                             |
   Mouse wheel up     |                      200 %  |                  400 %
   (wait)             |                             |
   Mouse wheel up     |                      400 %  |                  800 %

But if the user doesn't wait for the animation to be finished:

   User input         |  Zoom before the animation  |  Animation's end value
----------------------+-----------------------------+--------------------------
   Mouse wheel up     |                      100 %  |                  200 %
   Mouse wheel up     |                      110 %  |                  220 %
   Mouse wheel up     |                      120 %  |                  240 %

What I want (again, the user doesn't wait):

   User input         |  Zoom before the animation  |  Animation's end value
----------------------+-----------------------------+--------------------------
   Mouse wheel up     |                      100 %  |                  200 %
   Mouse wheel up     |  immediately jump to 200 %  |                  400 %
   Mouse wheel up     |  immediately jump to 400 %  |                  800 %

I hate applications where there can't be made a further user input until the end of an animation, and therefore I mostly hate smooth animations. So what I want is: When the user gives another user input and there is currently an animation running, "skip" this animation by jumping to the end of this animation.

The simpliest solution would be to just use the end value of the previous animation for the start value of the new one, but I want to abstract the "type" of animation which is currently performed; it doesn't have to be a zooming animation, but may also be a scrolling, panning, whatever animation.

So is there a possibility, without further knowledge of the animation (I only have a pointer to a QPropertyAnimation), to make it immediately jump to the end?

Currently, my code looks like this:

class View : ...
{ 
    // Property I want to animate using the mouse wheel
    Q_PROPERTY(qreal scale READ currentScale WRITE setScale)
    ...
private:
    // Pointer to the animation, which can also be another animation!
    QPropertyAnimation *viewAnimation;
}
void View::wheelEvent(QWheelEvent *e)
{
    qreal scaleDelta = pow(1.002, e->delta());
    qreal newScale = currentScale() * scaleDelta;

    if(viewAnimation)
    {
        // --- CODE SHOULD BE INSERTED HERE ---
        // --- Jump to end of viewAnimation ---
        // --- rather than canceling it     ---
        cancelViewAnimation();
    }
    viewAnimation = new QPropertyAnimation(this, "scale", this);
    viewAnimation->setStartValue(currentScale());
    viewAnimation->setEndValue(newScale);
    viewAnimation->setDuration(100);
    connect(viewAnimation, SIGNAL(finished()), SLOT(cancelViewAnimation()));
    viewAnimation->start();
}

void View::cancelViewAnimation()
{
    if(viewAnimation)
    {
        viewAnimation->stop();
        viewAnimation->deleteLater();
        viewAnimation = NULL;
    }
}
1

1 Answers

2
votes

I think this will do it:

if(viewAnimation)
{
    // jump to end of animation, without any further knowledge of it:
    viewAnimation->targetObject()->setProperty(viewAnimation->propertyName(),
                                               viewAnimation->endValue());
    cancelViewAnimation();
}