Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

Vous n'avez pas encore de compte Developpez.com ? L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Developpez.com

Qt

Choisissez la catégorie, puis la rubrique :

Viadeo Twitter Facebook Share on Google+   
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Toutes les fonctions  ·  Vues d'ensemble  · 

Le framework animation

Le framework animation fait partie du projet Kinetic, et vise à fournir un moyen facile pour la création d'interfaces graphiques animées et lisses. En animant les propriétés Qt, le framework fournit une grande liberté d'animation de widgets et de QObject. Le framework peut également être utilisé avec le framework Graphics View.

Dans cet aperçu, nous expliquons les bases de son architecture. Nous montrons également des exemples des techniques les plus courantes que le framework permet pour animer les QObject et les éléments graphiques.

L'architecture du framework animation

Nous allons dans cette section regarder le haut de l'architecture du framework animation et voir comment il est utilisé pour animer les propriétés Qt. Le diagramme suivant montre les classes les plus importantes du framework animation.

image

Les fondations du framework animation se composent de la classe de base QAbstractAnimation et de ses deux sous-classes, QVariantAnimation et QAnimationGroup. QAbstractAnimation est l'ancêtre de toutes les animations. Il représente les propriétés de base communes à toutes les animations du framework, notamment la capacité de démarrer, arrêter et mettre en pause une animation. Il reçoit également les notifications de changement du temps.

La framework animation prévoit en plus la classe QPropertyAnimation, qui hérite de QVariantAnimation et réalise l'animation d'une propriété Qt, qui fait partie du systéme meta-objet de Qt. La classe effectue une interpolation sur la propriété en utilisant un assouplissement de la courbe. Donc, quand vous voulez animer une valeur, vous pouvez la déclarer comme une propriété et faire de votre classe un QObject. Notez que cela nous donne une grande liberté dans l'animation de widgets déjà existants et d'autres QObject.

Des animations complexes peuvent être construites en créant une structure en arbre de QAbstractAnimation. L'arbre est créé en utilisant des QAnimationGroup, qui fonctionnent comme des conteneurs pour d'autres animations. Notez également que les groupes sont des sous-classes de QAbstractAnimation, ces groupes peuvent donc eux-mêmes contenir d'autres groupes.

Le framework animation peut être utilisé seul, mais est également conçu pour faire partie du framework machine à état (voir le framework machine à état pour une introduction à la machine à état de Qt). La machine à état fournit un état spécial qui peut jouer une animation. Un QState peut également définir des propriétés quand l'état est entered ou exited, et cet état spécial d'animation sera interpolé entre ces valeurs lorsqu'on lui donne une QPropertyAnimation. Nous allons examiner plus en détail cette partie par la suite.

À l'intérieur du framework, les animations sont contrôlées par un timer global, qui envoie des mises à jour à toutes les animations qui sont jouées.

Pour une description détaillée des fonctions de classes et de leur rôle dans le framework, vous pouvez regarder les descriptions des classes.

Les classes contenues dans le framework animation

Ces classes offrent un framework permettant de créer des animations à la fois simples et complexes.

QAbstractAnimation Base de toutes les animations.
QAnimationGroup Classe abstraite pour les groupes d'animations.
QEasingCurve Assouplissement de courbe pour contrôler les animations.
QParallelAnimationGroup Groupe d'animations parallèles.
QPauseAnimation Pause pour le QSequentialAnimationGroup.
QPropertyAnimation Anime les propriétés Qt.
QSequentialAnimationGroup Groupe d'animations séquentielles.
QTimeLine Ligne temporelle pour contrôler les animations.
QVariantAnimation Classe abstraite de base pour toutes les animations.

Animer les propriétés Qt

Comme mentionné dans la section précédente, la classe QPropertyAnimation peut interpoler des propriétés Qt. C'est cette classe qui doit être utilisée pour animer des valeurs. En fait, sa superclasse, QVariantAnimation, est abstraite et ne peut pas être utilisée directement.

Une des raisons majeures qui nous a poussé à choisir d'animer les propriétés Qt est que cela présente pour nous une grande liberté dans l'animation de classe existante dans l'API Qt. Notamment, la classe QWidget (que nous pouvons également intégrer dans un QGraphicsView) a des propriétés pour ses limites, ses couleurs, etc. Regardons ce petit exemple :

QPushButton button("Animated Button");
button.show();
 
QPropertyAnimation animation(&button, "geometry");
animation.setDuration(10000);
animation.setStartValue(QRect(0, 0, 100, 30));
animation.setEndValue(QRect(250, 250, 100, 30));
 
animation.start();

Ce code va déplacer un bouton du coin supérieur gauche de l'écran à la position (250, 250) en 10 secondes (10000 millisecondes).

L'exemple ci-dessus va réaliser une interpolation linéaire entre la valeur de début et la valeur de fin. Il est également possible de fixer des valeurs situées entre la valeur de début et la valeur de fin. L'interpolation passera ensuite par ces points.

QPushButton button("Animated Button");
button.show();
 
QPropertyAnimation animation(&button, "geometry");
animation.setDuration(10000);
 
animation.setKeyValueAt(0, QRect(0, 0, 100, 30));
animation.setKeyValueAt(0.8, QRect(250, 250, 100, 30));
animation.setKeyValueAt(1, QRect(0, 0, 100, 30));
 
animation.start();

Dans cet exemple, l'animation emmènera button à la position (250, 250) en huit secondes, puis le déplacera à sa position initiale au cours des deux dernières secondes. Le mouvement sera interpolé linéairement entre ces points.

Vous avez également la possibilité d'animer des valeurs d'un QObject qui n'est pas déclaré comme une propriété Qt. La seule exigence est que cette valeur ait un modificateur. Vous pouvez ensuite réaliser une sous-classe de la classe contenant la valeur et déclarer une propriété qui est utilisée par le modificateur. Notez que chaque propriété Qt exige un accesseur, vous devez donc fournir un accesseur vous-même s'il n'est pas défini.

class MyGraphicsRectItem : public QObject, public QGraphicsRectItem
{
    Q_OBJECT
    Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
};

Dans l'exemple de code ci-dessus, nous réalisons une sous-classe de QGraphicsRectItem et définissons une propriété géométrique. Nous pouvons maintenant animer la géométrie de widgets même si QGraphicsRectItem ne prévoit pas de propriété géométrique.

Pour une introduction générale au système de propriété Qt, voir sa vue d'ensemble.

Les animations et le framework Graphics View

Lorsque vous souhaitez animer des QGraphicsItems, vous utilisez également QPropertyAnimation. Toutefois, QGraphicsItem n'hérite pas QObject. Une bonne solution est de réaliser une sous-classe de l'élément graphique que vous souhaitez animer. Cette classe héritera ensuite également de QObject. De cette façon, QPropertyAnimation peut être utilisée pour les QGraphicsItems. L'exemple ci-dessous montre comment cela est fait. Une autre possibilité est d'hériter de QGraphicsWidget, qui est déjà un QObject.

class Pixmap : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
    Q_PROPERTY(QPointF pos READ pos WRITE setPos)
    ...

Comme décrit dans la section précédente, nous devons définir les propriétés que nous souhaitons animer.

Notez que QObject doit être la première classe héritée, il s'agit d'une exigence du système meta-objet.

Comme mentionné, QPropertyAnimation effectue une interpolation entre la valeur de la propriété du début à la fin. En plus d'ajouter plusieurs valeurs clés à l'animation, vous pouvez également utiliser un assouplissement de la courbe. L'assouplissement des courbes décrit une fonction qui contrôle la façon dont doit être définie la vitesse de l'interpolation entre 0 et 1, il est utile si vous voulez contrôler la vitesse d'une animation sans en changer la trajectoire de l'interpolation.

QPushButton button("Animated Button");
button.show();
 
QPropertyAnimation animation(&button, "geometry");
animation.setDuration(3000);
animation.setStartValue(QRect(0, 0, 100, 30));
animation.setEndValue(QRect(250, 250, 100, 30));
 
animation.setEasingCurve(QEasingCurve::OutBounce);
 
animation.start();

Ici, l'animation va suivre une courbe qui la fait rebondir comme une balle comme si elle avait été lâchée de la position du début à la fin. QEasingCurve a une grande collection de courbes que vous pouvez choisir. Elles sont définies par l'énumération QEasingCurve::type. Si vous avez besoin d'une autre courbe, vous pouvez également en implémenter une vous-même et l'enregistrer avec QEasingCurve.

Jouer des animations simultanément

Une application contiendra souvent plus d'une animation. Par exemple, vous pouvez vouloir déplacer plus d'un élément graphique simultanément ou les déplacer en séquence les uns après les autres.

Les sous-classes de QAnimationGroup (QSequentialAnimationGroup et QParallelAnimationGroup) sont des conteneurs pour d'autres animations, pour que celles-ci puissent être animées en séquence ou parallèlement. Le QAnimationGroup est un exemple d'animation qui n'anime pas les propriétés, mais il reçoit la notification de changement de temps périodiquement. Cela lui permet de transmettre ces changements de temps à ses animations contenues, et ainsi contrôler quand celles-ci sont jouées.

Regardons les exemples de code qui utilisent à la fois QSequentialAnimationGroup et QParallelAnimationGroup, en commençant par ce dernier.

QPushButton *bonnie = new QPushButton("Bonnie");
bonnie->show();
 
QPushButton *clyde = new QPushButton("Clyde");
clyde->show();
 
QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "geometry");
// Set up anim1
 
QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "geometry");
// Set up anim2
 
QParallelAnimationGroup *group = new QParallelAnimationGroup;
group->addAnimation(anim1);
group->addAnimation(anim2);
 
group->start();

Un groupe parallèle joue plus d'une animation à la fois. L'appel à sa fonction start() débutera toutes les animations qu'il gouverne.

QPushButton button("Animated Button");
button.show();
 
QPropertyAnimation anim1(&button, "geometry");
anim1.setDuration(3000);
anim1.setStartValue(QRect(0, 0, 100, 30));
anim1.setEndValue(QRect(500, 500, 100, 30));
 
QPropertyAnimation anim2(&button, "geometry");
anim2.setDuration(3000);
anim2.setStartValue(QRect(500, 500, 100, 30));
anim2.setEndValue(QRect(1000, 500, 100, 30));
 
QSequentialAnimationGroup group;
 
group.addAnimation(&anim1);
group.addAnimation(&anim2);
 
group.start();

Comme vous l'avez sans doute deviné, QSequentialAnimationGroup joue ses animations en séquence (dans l'ordre). Il commence l'animation suivante dans la liste après que la précédente soit terminée.

Puisqu'un groupe d'animations est une animation lui-même, vous pouvez l'ajouter à un autre groupe. De cette façon, vous pouvez construire une structure arborescente des animations qui spécifie quand celles-ci sont jouées les unes par rapport aux autres.

Machine à état et animations

Lorsque vous utilisez une machine d'état, il est possible d'associer une ou plusieurs animations à une transition entre états en utilisant la classe QSignalTransition ou QEventTransition. Ces classes sont toutes deux dérivées de QAbstractTransition, qui définit la fonction adéquate addAnimation() permettant l'apposition d'une ou plusieurs animations déclenchées lorsque la transition se produit.

Nous avons également la possibilité d'associer les propriétés avec les états plutôt que de fixer la valeur de début et la valeur de fin nous-même. Voici un exemple de code complet qui anime la géométrie d'un QPushButton.

QPushButton *button = new QPushButton("Animated Button");
button->show();
 
QStateMachine *machine = new QStateMachine;
 
QState *state1 = new QState(machine->rootState());
state1->assignProperty(button, "geometry", QRect(0, 0, 100, 30));
machine->setInitialState(state1);
 
QState *state2 = new QState(machine->rootState());
state2->assignProperty(button, "geometry", QRect(250, 250, 100, 30));
 
QSignalTransition *transition1 = state1->addTransition(button,
    SIGNAL(clicked()), state2);
transition1->addAnimation(new QPropertyAnimation(button, "geometry"));
 
QSignalTransition *transition2 = state2->addTransition(button,
    SIGNAL(clicked()), state1);
transition2->addAnimation(new QPropertyAnimation(button, "geometry"));
 
machine->start();

Pour un exemple plus complet sur la façon d'utiliser le framework de la machine à état, voir l'exemple des états (il est présent dans le répertoire

examples/animation/states

).

Remerciements

Merci à Jonathan Courtois pour la traduction et à Thibaut Cuvelier et à Jacques Thery pour leur relecture !

Warning: include(): https:// wrapper is disabled in the server configuration by allow_url_include=0 in /home/developpez/www/developpez-com/upload/qt/doc/bs.php on line 4 Warning: include(https://qt.developpez.com/index/rightColumn): failed to open stream: no suitable wrapper could be found in /home/developpez/www/developpez-com/upload/qt/doc/bs.php on line 4 Warning: include(): Failed opening 'https://qt.developpez.com/index/rightColumn' for inclusion (include_path='.:/usr/php53/lib/php') in /home/developpez/www/developpez-com/upload/qt/doc/bs.php on line 4
Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 4.6
Copyright © 2020 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur, une redirection cassée ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
Responsable bénévole de la rubrique Qt : Thibaut Cuvelier -

Partenaire : Hébergement Web