36. Animation Fremework
The Qt animation framework provides a way to animate GUI elements in Qt Widgets applications. It lets you animate a Qt property value change of a widget or a QObject
We have already seen the animation framework in action in Chapter 21, where we built an animated bar widget from a progress bar and a label. In this chapter we build several versions of a self-dismissing notification panel: we first animate the panel’s position, then its color, geometry and opacity, after which we demonstrate various easing curves, sequential, and parallel animation groups, ending the chapter with a pause animation demonstration.
36.1 QPropertyAnimation Basics
Not all UI transitions in polished desktop applications are instant - panels slide into view, buttons shift on click, and widgets expand to reveal content. QPropertyAnimation drives any Q_PROPERTY value from a start to an end value over a set duration, and is the foundation everything else in this chapter builds on.
![]() |
You need to build a |
To use a property animation in your application:
-
Create a
QPropertyAnimationinstance. For the purpose of this chapter we buildNotificationPanel, a custom panel inherited fromQFramethat has a label to display the notification message and a button to dismiss it. Because the panel will be animated, we add aQPropertyAnimationas an instance member. The constructor takes three arguments:- The animation target object. In this case,
self, theNotificationPanelinstance. - The target object’s property to animate as a
bytesvalue.posis aQPointholding the top-left corner position of the frame within its parent widget. For aQObject’s member to serve as an animation target it must be marked with Qt’sQ_PROPERTYmacro in C++, or with the@Propertydecorator in your PySide6 classes. - The animation’s Qt parent. Passing
selfties the animation’s lifetime to the panel in Qt’s object hierarchy.
We also set the animation duration to 500 milliseconds. The helper methods
target_x()andtarget_y()calculate the horizontal and vertical coordinates needed to center the panel within its parent. Set the animation start and end values. A new
NotificationPanelis created for each notification (inshow_notification()on the main window). Inshow_panel()we set theposstart value to a position just off the left edge of the parent (QPoint(-self.width(), self.target_y())), and the end value to the centered position within the parent.Start the animation. Call
show()to make the panel visible, thenQPropertyAnimation.start()to begin the animation. The panel’sposis interpolated from the start value to the end value over 500 milliseconds, ending up centered in the parent. Clicking the Dismiss button callsdeleteLater(), which removes the panel from memory once Qt returns to the event loop.
Once you start the application it should look like this:

target_x() and target_y() are evaluated once when show_panel() is called. If the main window is resized while the animation is still running, the panel will land at the position calculated before the resize rather than the new center. For a production application you would recalculate the end value in a resizeEvent() handler. For the examples in this chapter the edge case is ignored to keep the focus on the animation mechanics.
36.2 Animating Color, Geometry, and Opacity
Position is only one of many properties you can animate - any value exposed through Qt’s property system is a valid target. In this section we set up three animations on the same widget: a color transition, a fade-in, and an expanding entrance. Color and opacity animate straightforwad from fixed values, but geometry requires a little more work: because the widget’s position isn’t known until it’s been placed by its parent, the start and end QRect values have to be set at show time rather than in __init__().
![]() |
Your task is to turn the sliding frame from the previous exercise into a status panel. You need to allow the users to choose from three separate |
- Color, which animates a custom property to drive a color transition on the message label from yellow to green.
- Opacity, which fades the panel in from fully transparent to fully opaque.
- Geometry, which expands the panel from a single point to its full size.
To animate widget color, geometry, and opacity in your application:
- Create a color animation. Qt widgets do not expose a color property, so for the notification panel we introduce
ColoredLabel, aQLabelsubclass that declares a customcolorproperty of typeQColor. Its setter applies the color to the label background via QSS. Create an animation targeting this property that interpolates from yellow to green over 1000 milliseconds.
Create an opacity animation. Qt widgets do not expose an opacity property directly - opacity is handled via
QGraphicsOpacityEffect. Create an instance, attach it toNotificationPanelwithsetGraphicsEffect(), then create an animation targeting the effect’sopacityproperty and interpolate from0.0(fully transparent) to1.0(fully opaque) over 1000 milliseconds.Create a geometry animation. A widget’s geometry includes its position within the parent, which is not known at construction time. For this reason the start and end
QRectvalues are calculated insetup_geometry_animations(), called fromshow_panel()just before the panel is shown. The start rect collapses the panel to a single pixel at the center of its final position. The end rect is the full-size centered rect.Store the animations in a dictionary keyed by
AnimationType. TheAnimationTypeenum is passed into the panel’s constructor so the correct animation is selected up front. The main window provides a combobox for selecting the animation type. A newNotificationPanelis created for each notification with the currently selected type.
When you run the application, select an animation type from the combobox and click the button to show the notification panel playing the selected animation.

36.3 Easing Curves
A linear animation has constant speed (the same distance per frame from start to finish) which can feel mechanical. Easing curves remap elapsed time to progress non-linearly, giving motion a sense of weight, momentum, or snap.
![]() |
You are tasked with selecting an appropriate easing curve for the notification panel. You add all available easing curve to a combobox so the user can select which one will be applied before the panel is shown. |
To inspect different easing curve types:
-
Populate the combobox. Iterate over
QEasingCurve.Typewhich exposes all registered curve types and store each enum value as item data. Skip the curve types listed inEXCLUDEC_CURVE_TYPES:Custom- requires a user-supplied callback installed viasetCustomType(). Without one, passing it tosetEasingCurve()raises an error.NCurveTypes- a sentinel value equal to the total count of curve types in the enum, used internally by Qt for bounds checking. It has no curve implementation.BezierSplineandTCBSpline- user-defined spline types that require control points to be added manually viaaddCubicBezierSegment()andaddTCBSegment()respectively before they have a defined shape.InCurveandOutCurve- Internal values.SineCurveandCosineCurve- implement oscillating waveforms. The animated property does not end up atendValue()when the animation finishes.
SineCurveandCosineCurveare particularly dangerous: they break the promise ofQpropertyAnimationthat the animated property will end atendValue()when the animation finishes.InCurve,OutCurve,SineCurveandCosineCUrveare absent from the Qt documentation so you should not use them either. Set the easing curve. When the user clicks the button,
show_notification(s)reads the currently selected curve from the combobox and passes it toNotificationPanel.set_easing_curve(), which forwards it toself.animation.setEasingCurve()before the animation starts.
- Show the notification.
show_panel()is called with a randomly chosen message fromMESSAGES. The animation runs with whichever curve is currently selected in the combobox.
When you select a curve and click the button, the panel covers the same distance every time but with a different animation type.
36.4 Sequential Animation Groups
Some transitions require steps in order - a panel slides in, then its label appears, then the Dismiss button pulses with a glow. Wiring this with signals is brittle. QSequentialAnimationGroup chains animations so each starts only when the previous one finishes, and the whole sequence is controlled through a single object.
![]() |
You restructure the notification panel’s entrance into three ordered phases: it slides in from off-screen, its message label fades up, and finally the Dismiss button pulses with an orange glow. |
All three animations go into a single QSequentialAnimationGroup started with one call.
To use a sequential animation group in your application:
-
Create the individual animations. Create three animations:
- A position animation that moves the panel from off-screen to the center of the main window.
- An opacity animation that fades the message label in from
0.0to1.0via aQGraphicsOpactyEffect. - A glow animation that raises
blurRadiusof aQgraphicsDropShadowEffectattached to the Dismiss button from0to10.
Create the animation group and add the animations. Create a
QSequentialAnimationGroupand add the three animations in the order they will play: position first , then opacity, then glow.Start the group instead the individual animations. In
show_panel(), set the start and end values for the position animation, then callstart()on the group. One call drives all three animations in sequence.
When you run the application and click the button, the panel slides to the center of the window, the message label fades in, and finally the Dismiss button gets an orange glow.

36.5 Parallel Animation Groups
Where sequential groups enforce order, QParallelAnimationGroup runs all its children simultaneously, making it the right tool when several properties should change together as one cohesive motion.
![]() |
You replace the notification panel’s slide-only entrance with a combined effect: position and opacity animate in parallel, so the panel slides in while fading from transparent to opaque. Dismiss reverses the same group before deleting the panel. |
To use a parallel animation group in your application:
Create the individual animations. As in the previous section, create a position animation and an opacity animation. This time both are set to 1000 milliseconds (This doesn’t always have to be the case, and the group finishes only when the longest child finishes). Set
OutBounceas the easing curve for the position animation inshow_panel().Create the group and add both animations. Create a
QParallelAnimationGroupand add the position and opacity animations to it. UnlikeQSequentialAnimationGroup, you can’t use pauses here: both animations start at the same moment.Start the animation group.
Rather than discarding the panel immediatelly as in the sequential animation group example, hide_panel() calls anim_group.setDirection(Backward) and restarts the group, which plays both animations in reverse - the panel slides back off-screen while fading out. deleteLater() is connected to finished so the panel is cleaned up only after the reverse animation completes.
When a QParallelAnimationGroup contains animations of different durations and is reversed, shorter animations do not start immediately - they are delayed by the difference between their duration and the group’s total duration. A 300ms animation inside a 1000ms group will sit idle for 700ms before playing in reverse.
When you run the application the panel bounces in while fading up. Clicking Dismis fades and slides it back out before it is destroyed.
36.6 Pause Animations
QPauseAnimation is a duration-only animation - it doesn’t have any visual effects. Its purpose is to introduce pauses inside a QSequentialAnimationGroup without having to use a QTimer.
![]() |
You complete the notification panel by giving it self-dismissing behaviour: on trigger, the position animation plays, waits via a |
To use a pause animation in your application:
Create the animations. Create the position and the opacity animations.
Create the animation group and add the animations including the pause. Add the animation in order: slide-in, pause, and fade-out. The group drives the entire lifecycle of the panel with a single
start()call inshow_panel(). It is not necessary to construct aQPauseAnimationyourself.QSequentialAnimationGroupprovides the convenience functionsaddPause()andinsertPause()for that.
It is possible that the user dismisses the panel while the animation group is still playing. dismiss() checks whether the opacity animation is already running (which indicates that the auto-dismiss fade is already in progress) and does nothing in that case. Otherwise it stops the group, starts the opacity animation directly, and connect its finished signal to deleteLater().
When you run the applicatio the panel slides in, holds for the specified duration, then fades out on its own. Clicking Dismiss at any point before the fade begins triggers the same fade-out immediatelly.
