diff options
Diffstat (limited to 'src/corelib/animation')
-rw-r--r-- | src/corelib/animation/qanimationgroup.cpp | 54 | ||||
-rw-r--r-- | src/corelib/animation/qparallelanimationgroup.cpp | 23 | ||||
-rw-r--r-- | src/corelib/animation/qpauseanimation.cpp | 16 | ||||
-rw-r--r-- | src/corelib/animation/qpropertyanimation.cpp | 4 | ||||
-rw-r--r-- | src/corelib/animation/qpropertyanimation_p.h | 1 | ||||
-rw-r--r-- | src/corelib/animation/qsequentialanimationgroup.cpp | 33 | ||||
-rw-r--r-- | src/corelib/animation/qvariantanimation.cpp | 99 | ||||
-rw-r--r-- | src/corelib/animation/qvariantanimation_p.h | 4 |
8 files changed, 166 insertions, 68 deletions
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp index 8c9f358..0745d39 100644 --- a/src/corelib/animation/qanimationgroup.cpp +++ b/src/corelib/animation/qanimationgroup.cpp @@ -41,23 +41,51 @@ /*! \class QAnimationGroup - \brief The QAnimationGroup class is an abstract base class for group of animations. + \brief The QAnimationGroup class is an abstract base class for groups of animations. \since 4.5 \ingroup group_animation \preliminary - QAnimationGroup represents a group of animations, such as parallel or sequential, - and lets you combine different animations into one. The group manages any animation - that inherits QAbstractAnimation. By combining groups, you can easily construct - complex animation graphs. - - The QAnimationGroup base class provides methods for adding and retrieving animations. - Besides that, you can remove animations by calling remove(), and clear the animation - group by calling clearAnimations(). You may keep track of changes in the group's animations by - listening to QEvent::ChildAdded and QEvent::ChildRemoved events. - - QAnimationGroup takes ownership of the animations it manages, and ensures that they are - deleted when the animation group is deleted. + An animation group is a container for animations (subclasses of + QAbstractAnimation). A group is usually responsible for managing + the \l{QAbstractAnimation::State}{state} of its animations, i.e., + it decides when to start, stop, resume, and pause them. Currently, + Qt provides two such groups: QParallelAnimationGroup and + QSequentialAnimationGroup. Look up their class descriptions for + details. + + Since QAnimationGroup inherits from QAbstractAnimation, you can + combine groups, and easily construct complex animation graphs. + You can query QAbstractAnimation for the group it belongs to + (using the \l{QAbstractAnimation::}{group()} function). + + To start a top-level animation group, you simply use the + \l{QAbstractAnimation::}{start()} function from + QAbstractAnimation. By a top-level animation group, we think of a + group that itself is not contained within another group. Starting + sub groups directly is not supported, and may lead to unexpected + behavior. + + \omit OK, we'll put in a snippet on this here \endomit + + QAnimationGroup provides methods for adding and retrieving + animations. Besides that, you can remove animations by calling + remove(), and clear the animation group by calling + clearAnimations(). You may keep track of changes in the group's + animations by listening to QEvent::ChildAdded and + QEvent::ChildRemoved events. + + \omit OK, let's find a snippet here as well. \endomit + + QAnimationGroup takes ownership of the animations it manages, and + ensures that they are deleted when the animation group is deleted. + + You can also use a \l{The State Machine Framework}{state machine} + to create complex animations. The framework provides a special + state, QAnimationState, that plays an animation upon entry and + transitions to a new state when the animation has finished + playing. This technique can also be combined with using animation + groups. \sa QAbstractAnimation, QVariantAnimation, {The Animation Framework} */ diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index a75f85c..68dbb9e 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -46,8 +46,27 @@ \ingroup group_animation \preliminary - The animations are all started at the same time, and run in parallel. The animation group - finishes when the longest lasting animation has finished. + QParallelAnimationGroup--a \l{QAnimationGroup}{container for + animations}--starts all its animations when it is + \l{QAbstractAnimation::start()}{started} itself, i.e., runs all + animations in parallel. The animation group finishes when the + longest lasting animation has finished. + + You can treat QParallelAnimation as any other QAbstractAnimation, + e.g., pause, resume, or add it to other animation groups. + + \code + QParallelAnimationGroup *group = new QParallelAnimationGroup; + group->addAnimation(anim1); + group->addAnimation(anim2); + + group->start(); + \endcode + + In this example, \c anim1 and \c anim2 are two + \l{QPropertyAnimation}s that have already been set up. + + \sa QAnimationGroup, QPropertyAnimation, {The Animation Framework} */ #ifndef QT_NO_ANIMATION diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp index 86c3049..cf3bb3b 100644 --- a/src/corelib/animation/qpauseanimation.cpp +++ b/src/corelib/animation/qpauseanimation.cpp @@ -45,6 +45,22 @@ \since 4.5 \ingroup group_animation \preliminary + + If you wish to introduce a delay between animations in a + QSequentialAnimationGroup, you can insert a QPauseAnimation. This + class does not animate anything, but does not + \l{QAbstractAnimation::finished()}{finish} before a specified + number of milliseconds have elapsed from when it was started. You + specify the duration of the pause in the constructor. It can also + be set directly with setDuration(). + + It is not necessary to construct a QPauseAnimation yourself. + QSequentialAnimationGroup provides the convenience functions + \l{QSequentialAnimationGroup::}{addPause()} and + \l{QSequentialAnimationGroup::}{insertPauseAt()}. These functions + simply take the number of milliseconds the pause should last. + + \sa QSequentialAnimationGroup */ #ifndef QT_NO_ANIMATION diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index ed20e667..4bdffa4 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -48,14 +48,14 @@ QPropertyAnimation interpolates over \l{Qt's Property System}{Qt properties}. As property values are stored in \l{QVariant}s, the class inherits QVariantAnimation, and supports animation of the - same \l{QVariant::Type}{variant types} as its super class. + same \l{QVariant::Type}{variant types} as its super class. A class declaring properties must be a QObject. To make it possible to animate a property, it must provide a setter (so that QPropertyAnimation can set the property's value). Note that this makes it possible to animate many of Qt's widgets. Let's look at an example: - + \code QPropertyAnimation animation(myWidget, "geometry"); animation.setDuration(10000); diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h index ed3666d..9d9dd31 100644 --- a/src/corelib/animation/qpropertyanimation_p.h +++ b/src/corelib/animation/qpropertyanimation_p.h @@ -70,7 +70,6 @@ public: { } - QPointer<QObject> target; //for the QProperty diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp index 45673c2..c610b4f 100644 --- a/src/corelib/animation/qsequentialanimationgroup.cpp +++ b/src/corelib/animation/qsequentialanimationgroup.cpp @@ -46,13 +46,36 @@ \ingroup group_animation \preliminary - The first animation in the group is started first, and when it finishes, the next animation - is started, and so on. The animation group finishes when the last animation has finished. + QSequentialAnimationGroup is a QAnimationGroup that runs its + animations in sequence, i.e., it starts one animation after + another has finished playing. The animations are played in the + order they are added to the group (using + \l{QAnimationGroup::}{addAnimation()} or + \l{QAnimationGroup::}{insertAnimationAt()}). The animation group + finishes when its last animation has finished. - At each moment there is at most one animation that is active in the group, called currentAnimation. - An empty group has no current animation. + At each moment there is at most one animation that is active in + the group; it is returned by currentAnimation(). An empty group + has no current animation. - You can call addPause() or insertPause() to add a pause to a sequential animation group. + A sequential animation group can be treated as any other + animation, i.e., it can be started, stopped, and added to other + groups. You can also call addPause() or insertPauseAt() to add a + pause to a sequential animation group. + + \code + QSequentialAnimationGroup group; + + group.addAnimation(anim1); + group.addAnimation(anim2); + + group.start(); + \endcode + + In this example, \c anim1 and \c anim2 are two already set up + \l{QPropertyAnimation}s. + + \sa QAnimationGroup, QAbstractAnimation, {The Animation Framework} */ #ifndef QT_NO_ANIMATION diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 331024e..e27cde8 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -64,13 +64,15 @@ QT_BEGIN_NAMESPACE shared functionality. QVariantAnimation cannot be used directly as it is an abstract - class; it does not implement \l{updateCurrentValue()}. The class - performs interpolation over \l{QVariant}s, but leaves using the - interpolated values to its subclasses. Currently, Qt provides - QPropertyAnimation, which animates Qt \l{Qt's Property System} - {properties}. See the QPropertyAnimation class description if you - wish to animate such properties. - + class; it does not implement + \l{QAbstractAnimation::}{updateCurrentValue()} from + QAbstractAnimation. The class performs interpolation over + \l{QVariant}s, but leaves using the interpolated values to its + subclasses. Currently, Qt provides QPropertyAnimation, which + animates Qt \l{Qt's Property System}{properties}. See the + QPropertyAnimation class description if you wish to animate such + properties. + You can then set start and end values for the property by calling setStartValue() and setEndValue(), and finally call start() to start the animation. QVariantAnimation will interpolate the @@ -109,12 +111,12 @@ QT_BEGIN_NAMESPACE \o \l{QMetaType::}{QSizeF} \o \l{QMetaType::}{QRect} \o \l{QMetaType::}{QRectF} - \endlist + \endlist If you need to interpolate other variant types, including custom types, you have to implement interpolation for these yourself. You do this by reimplementing interpolated(), which returns - interpolation values for the value being interpolated. + interpolation values for the value being interpolated. \omit We need some snippets around here. \endomit @@ -150,7 +152,7 @@ template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF f.getRect(&x1, &y1, &w1, &h1); qreal x2, y2, w2, h2; t.getRect(&x2, &y2, &w2, &h2); - return QRectF( _q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress), + return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress), _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress)); } @@ -172,47 +174,61 @@ void QVariantAnimationPrivate::convertValues(int t) if (pair.second.userType() != t) pair.second.convert(static_cast<QVariant::Type>(t)); } - currentInterval.start.first = 2; // this will force the refresh - interpolator = 0; // if the type changed we need to update the interpolator + interpolator = 0; // if the type changed we need to update the interpolator } /*! - \fn void QVariantAnimation::updateCurrentValue(const QVariant &value) = 0; - This pure virtual function is called when the animated value is changed. - \a value is the new value. + \internal + The goal of this function is to update the currentInterval member. As a consequence, we also + need to update the currentValue. + Set \a force to true to always recalculate the interval. */ - -void QVariantAnimationPrivate::updateCurrentValue() +void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/) { - Q_Q(QVariantAnimation); + // can't interpolate if we have only 1 key value + if (keyValues.count() <= 1) + return; + const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration))); - if (progress < currentInterval.start.first || progress > currentInterval.end.first) { + if (force || progress < currentInterval.start.first || progress > currentInterval.end.first) { //let's update currentInterval - QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(), keyValues.constEnd(), qMakePair(progress, QVariant()), animationValueLessThan); + QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(), + keyValues.constEnd(), + qMakePair(progress, QVariant()), + animationValueLessThan); QVariantAnimation::KeyValues::const_iterator itEnd = itStart; // If we are at the end we should continue to use the last keyValues in case of extrapolation (progress > 1.0). // This is because the easing function can return a value slightly outside the range [0, 1] if (itStart != keyValues.constEnd()) { - - //this can't happen because we always prepend the default start value there - if (itStart == keyValues.begin()) { + // this can't happen because we always prepend the default start value there + if (itStart == keyValues.constBegin()) { ++itEnd; - if (itEnd == keyValues.constEnd()) - return; //there is no upper bound } else { --itStart; } - //update all the values of the currentInterval + // update all the values of the currentInterval currentInterval.start = *itStart; currentInterval.end = *itEnd; } } + setCurrentValueForProgress(progress); +} + +void QVariantAnimationPrivate::setCurrentValue() +{ + const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration))); + setCurrentValueForProgress(progress); +} - const qreal startProgress = currentInterval.start.first, - endProgress = currentInterval.end.first; +void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress) +{ + Q_Q(QVariantAnimation); + + const qreal startProgress = currentInterval.start.first; + const qreal endProgress = currentInterval.end.first; const qreal localProgress = (progress - startProgress) / (endProgress - startProgress); QVariant ret = q->interpolated(currentInterval.start.second, @@ -225,11 +241,10 @@ void QVariantAnimationPrivate::updateCurrentValue() #endif if (currentValue != ret) { //the value has changed - emit q->valueChanged(currentValue); + emit q->valueChanged(currentValue); } } - QVariant QVariantAnimationPrivate::valueAt(qreal step) const { QVariantAnimation::KeyValues::const_iterator result = @@ -240,7 +255,6 @@ QVariant QVariantAnimationPrivate::valueAt(qreal step) const return QVariant(); } - void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value) { if (step < qreal(0.0) || step > qreal(1.0)) { @@ -255,15 +269,14 @@ void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value) keyValues.insert(result, pair); } else { if (value.isValid()) - result->second = value; //remove the previous value + result->second = value; // replaces the previous value else if (step == 0 && !hasStartValue && defaultStartValue.isValid()) - result->second = defaultStartValue; //we reset to the default start value + result->second = defaultStartValue; // resets to the default start value else - keyValues.erase(result); //replace the previous value + keyValues.erase(result); // removes the previous value } - currentInterval.start.first = 2; // this will force the refresh - updateCurrentValue(); + recalculateCurrentInterval(/*force=*/true); } void QVariantAnimationPrivate::setDefaultStartValue(const QVariant &value) @@ -322,7 +335,7 @@ void QVariantAnimation::setEasingCurve(const QEasingCurve &easing) { Q_D(QVariantAnimation); d->easing = easing; - d->updateCurrentValue(); + d->recalculateCurrentInterval(); } Q_GLOBAL_STATIC(QVector<QVariantAnimation::Interpolator>, registeredInterpolators) @@ -433,7 +446,7 @@ void QVariantAnimation::setDuration(int msecs) if (d->duration == msecs) return; d->duration = msecs; - d->updateCurrentValue(); + d->recalculateCurrentInterval(); } /*! @@ -543,8 +556,8 @@ void QVariantAnimation::setKeyValues(const KeyValues &keyValues) Q_D(QVariantAnimation); d->keyValues = keyValues; qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan); - d->currentInterval.start.first = 2; // this will force the refresh d->hasStartValue = !d->keyValues.isEmpty() && d->keyValues.at(0).first == 0; + d->recalculateCurrentInterval(/*force=*/true); } /*! @@ -569,7 +582,7 @@ QVariant QVariantAnimation::currentValue() const { Q_D(const QVariantAnimation); if (!d->currentValue.isValid()) - const_cast<QVariantAnimationPrivate*>(d)->updateCurrentValue(); + const_cast<QVariantAnimationPrivate*>(d)->recalculateCurrentInterval(); return d->currentValue; } @@ -585,12 +598,10 @@ bool QVariantAnimation::event(QEvent *event) \reimp */ void QVariantAnimation::updateState(QAbstractAnimation::State oldState, - QAbstractAnimation::State newState) + QAbstractAnimation::State newState) { Q_UNUSED(oldState); Q_UNUSED(newState); - Q_D(QVariantAnimation); - d->currentValue = QVariant(); // this will force the refresh } /*! @@ -633,7 +644,7 @@ void QVariantAnimation::updateCurrentTime(int msecs) { Q_D(QVariantAnimation); Q_UNUSED(msecs); - d->updateCurrentValue(); + d->recalculateCurrentInterval(); } QT_END_NAMESPACE diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h index 14a3ef6..9e81649 100644 --- a/src/corelib/animation/qvariantanimation_p.h +++ b/src/corelib/animation/qvariantanimation_p.h @@ -108,7 +108,9 @@ public: quint32 changedSignalMask; - void updateCurrentValue(); + void setCurrentValue(); + void setCurrentValueForProgress(const qreal progress); + void recalculateCurrentInterval(bool force=false); void setValueAt(qreal, const QVariant &); QVariant valueAt(qreal step) const; void convertValues(int t); |