QPropertyAnimationを使用して、ウィジェット内を移動するためのユーザー入力をアニメーション化します。つまり、マウスホイールを使用してズームをスムーズにするために使用します。
現在、ユーザーが新しい入力を行う(マウスホイールを回転させる)と、現在のアニメーションがキャンセルされ、ズームプロパティの現在の値から新しいアニメーションが開始されます。
たとえば、ズームイン操作でビューを2倍に拡大縮小すると、次のシナリオを想像できます。
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 %
ただし、ユーザーがアニメーションの終了を待たない場合は、次のようになります。
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 %
私が欲しいもの(ここでも、ユーザーは待ちません):
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 %
アニメーションが終了するまでユーザー入力ができないアプリケーションは嫌いなので、スムーズなアニメーションはほとんど嫌いです。つまり、ユーザーが別のユーザー入力を行い、現在アニメーションが実行されている場合は、このアニメーションの最後にジャンプして、このアニメーションを「スキップ」します。
最も簡単な解決策は、前のアニメーションの終了値を新しいアニメーションの開始値として使用することですが、現在実行されているアニメーションの「タイプ」を抽象化したいと思います。ズームアニメーションである必要はありませんが、スクロール、パンなどのアニメーションでもかまいません。
それで、アニメーションの知識がなくても(私はへのポインタしか持っていませんQPropertyAnimation
)、すぐに最後にジャンプする可能性はありますか?
現在、私のコードは次のようになっています。
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;
}
}