IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

Animation en Qt


Sujet :

Qt

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 8
    Par défaut Animation en Qt
    Bonjour à tous !

    Voilà donc je réalise une petite animation sur les Tours de Hanoi, seulement j'ai un petit problème, mon algo marche bien, il se fini normalement seulement je ne sais pas comment rafraîchir ma QGraphicsScene, c'est à dire que le temps qu'elle se rafraîchisse (si je la rafraîchis bien) mon algo a fini donc on ne voit pas l'évolution des déplacements comme je le voudrais !

    J'ai essayé diverses méthodes comme les QTimer en passant par QMutex, qSleep et qWait mais sans succès, la seule personne qui m'a répondu sur çà m'a dit "Utilise des Threads" seulement les Threads c'est eee comment dire tout compliqué ...

    Mon programme se déroule comme suit:
    Un QWidget s'ouvre où l'on choisit le nombre de disque (entre 3 et 8) puis si on clique sur "GO" alors la QDialogue où il y a la scène des tours d'Hanoi apparaît.

    Je vous mets le code de la QDialog en question.

    Le .h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    #ifndef HEADER_ANIMATION
    #define HEADER_ANIMATION
     
    #include <QtGui>
     
    /* Structure où seront stockés les différents rectangles */ 
    typedef struct rectangle{
    	QRect q;
    	QColor in;
    	int taille;
    }Rect;
     
    class Animation : public QDialog
    {
        Q_OBJECT
     
        public:
        Animation(int x, QWidget *parent);
     
        private slots:
        void Fond(); /* Création du fond de la scène */
        void Rectangles(); /* Affichage des rectangles sur la scène */
        void hanoi(int x, QVector<Rect> &t1, QVector<Rect> &t3, QVector<Rect> &t2);
        void bouger(QVector<Rect> &t1, QVector<Rect> &t3);
     
        private:
        QGraphicsScene *scene;
        QPushButton *quitter;
     
        /* Éléments du fond de la scène */
        QGraphicsItem *base;
        QGraphicsItem *baton1, *baton2, *baton3;
     
        /* Vecteurs représentants les 3 tours de Hanoi */
        QVector<Rect> tour1, tour2, tour3;
     
        Rect tmp;
    };
     
    #endif
    Le .cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
     
    #include "Animation.h"
     
    Animation::Animation(int x, QWidget *parent = 0) : QDialog(parent)
    {
    	QColor couleur[] = {Qt::darkRed, Qt::cyan, Qt::magenta, Qt::gray, Qt::green, Qt::yellow, Qt::red, Qt::blue};
     
    	/* On stock les x rectangles voulu dans la première tour */
    	for (int i = 0; i<x ; i++) {
    		tmp.q = QRect(-150+(i*5), 100-(i*25), 100-(i*10), -25);
    		tmp.taille = 100-(i*10);
    		tmp.in = couleur[i];
    		tour1.push_back(tmp);
    	}
     
    	Fond(); /* On crée le fond */
    	Rectangles(); /* Et on ajoute les rectangles */
     
    	hanoi(x, tour1, tour3, tour2); /* Puis on lance l'algorithme sur les tours d'Hanoi */
    }
     
    /* Création du fond de la scène */
    void Animation::Fond() {
     
    	scene =  new QGraphicsScene(-200, -200, 400, 400);
     
    	QPen pen(Qt::black, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
     
    	base = scene->addLine(QLine(-150, 100, 150, 100), pen);
    	baton1 = scene->addLine(QLine(0, 100, 0, -100), pen);
    	baton2 = scene->addLine(QLine(100, 100, 100, -100), pen);
    	baton3 = scene->addLine(QLine(-100, 100, -100, -100), pen);
     
    	base->setZValue(-1); baton1->setZValue(-1); baton3->setZValue(-1); baton2->setZValue(-1);
     
    	QGraphicsView *vue = new QGraphicsView(scene, this);
     
    	vue->setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing);
    	vue->setGeometry(50, 50, 405, 405);
    	vue->setStyleSheet("background-color: #FFFFFF");
     
    	setFixedSize(510,510);
     
    	quitter = new QPushButton("Quitter", this);
    	quitter->setGeometry(180, 480, 150, 20);
     
    	connect(quitter,SIGNAL(clicked()),this, SLOT(accept()));
    }
     
    /* Ajout des rectangles dans la scène */
    void Animation::Rectangles() {
     
    	QPen pen(Qt::black, 1, Qt::SolidLine);
     
    	for (int i = 0; i<(int)tour1.size() ; i++) {
    		tour1[i].q = QRect(-100-(tour1[i].taille/2), 100-(i*25), tour1[i].taille, -25);
    		scene->addRect(tour1[i].q,pen,tour1[i].in);
    	}
    	for (int i = 0; i<(int)tour2.size() ; i++) {
    		tour2[i].q = QRect(0-(tour2[i].taille/2), 100-(i*25), tour2[i].taille, -25);
    		scene->addRect(tour2[i].q,pen,tour2[i].in);
    	}
    	for (int i = 0; i<(int)tour3.size() ; i++) {
    		tour3[i].q = QRect(100-(tour3[i].taille/2), 100-(i*25), tour3[i].taille, -25);
    		scene->addRect(tour3[i].q,pen,tour3[i].in);
    	}
    }
     
    /* Algorithme de résolution */
    void Animation::hanoi(int x, QVector<Rect> &t1, QVector<Rect> &t3, QVector<Rect> &t2){
     
    	if ( x > 0 ) {
    		hanoi(x-1, t1, t2, t3);
                    bouger(t1, t3);
                    hanoi(x-1, t2, t3, t1);
    	}
    }
     
    void Animation::bouger(QVector<Rect> &t1, QVector<Rect> &t3) {
     
    	Rect tmp = t1.back();
    	t1.pop_back();
    	t3.push_back(tmp);
     
    	/* Méthode de rafraîchissement brute */
    	delete scene; /* On supprime la scène */
    	Fond();       /* Et on recréer le fond */
    	Rectangles(); /* Et on place les rectangles à leur nouvelle place */
    }
    Désolé pour le patté que ça fait ...
    Et merci d'avance pour ceux qui prendront le temps de lire/comprendre et de me répondre

    Si besoin vous trouverez le programme complet ici:
    Hanoi

  2. #2
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Tu as regardé le tout nouveau Qt Animation Framework ?

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 8
    Par défaut
    Non du tout car cette animation étant un exercice de cours je dois la faire avec la classe QGraphicsScene seulement.
    Pour ma culture je m'informerai dessus surtout si cela peut me simplifier la tache à l'avenir !

    Pas d'idée sinon pour mon problème ?
    Déjà est ce que le code est bien construit ?
    Existe-il une méthode plus simple utilisant les QGraphicsScene ?
    Comment puis-je rafraichir mon animation à chaque mouvement ?

    Bouhou ça m'énerve, bloquer pendant une semaine sur un truc aussi ...

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Par défaut
    Alors d'abord, si j'ai bien compris, à chaque fois, tu supprimes ta scène et tu la recrée, ce n'est pas la bonne solution.

    Tu devrais regarder du côté de QGraphicsItem, qui est en fait la classe qui représente un élément dans ta scène (par exemple un rectangle). Ensuite, tu as juste à lui changer sa position, sans avoir à tout supprimer et tout recréer.

    La seconde chose, c'est le rafraichissement. Celui ci est géré par la QGraphicsView. Il y a plusieurs moyen de gérer ce rafraichissement. Si tu veux tout controler, alors il faut utiliser le QGraphicsView::NoViewPortUpdate et ensuite faire des repaint() (ou update() ) de ta view aux instants qui t'intéressent.

    En éspérant t'avoir aidé.

    G.

  5. #5
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Et pour gérer le temps de l'animation regarde QTimeLine

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 8
    Par défaut
    Bonjour et désolé pour le retard j'ai eu pas mal de travail ces derniers temps et donc j'ai un peu laissé cette animation de côté jusqu'à ce soir.

    Donc tout d'abord merci pour vos réponses

    Ensuite pour les QGraphicsItem et les QTimer je ne vois pas comment faire.

    Comment dans mon cas je peux déplacer mon rectangles au bon endroit directement ?
    Car pour chaque tour et position dans la tour cela est calculé avec la fonction Rectangles();
    Puis il faudrait que je regarde dans quelle tour il arrive et à quelle position à chaque fois, non ?
    Il n'existerait pas une méthode qui me permet de supprimer juste mes 3 tours et de les redessiner à chaque fois ?

    Sinon pour les QTimer j'ai compris comment cela marchait mais je ne vois pas comment m'en servir dans mon cas car il fait bien une mise à jour de l'animation toutes les N secondes mais l'algo derrière ne se stoppe pas et je ne vois pas comment faire.


    Pour finir j'ai essayé d'utiliser QGraphicsView::NoViewPortUpdate mais les update() et repaint() n'ont aucun effet sur mon animation

    Si vous aviez un exemple d'utilisation pour chacun voir plus ça m'aiderait grandement car même si cette animation n'est plus une priorité j'aimerais bien pouvoir la finir complètement.

    Encore merci pour votre aide

  7. #7
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par DebiloBob Voir le message
    Sinon pour les QTimer j'ai compris comment cela marchait mais je ne vois pas comment m'en servir dans mon cas car il fait bien une mise à jour de l'animation toutes les N secondes mais l'algo derrière ne se stoppe pas et je ne vois pas comment faire.
    EN faite, c'est plutôt ton algo qui devrais se déroulé au rythm du QTimer
    EN gros tout les T, tu avance ton algo d'un mouvement de pièce.

    Pour l'animation, ca dépend ce que tu veut faire. EN gros, tu as un point de début et un point de fin. Et pendant l'évolution du temps du calcule la position actuelle.
    Lis ceci
    http://www.developpez.net/forums/d82...aces-modernes/ ca explique un peu le principe.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 8
    Par défaut
    J'ai trouvé une solution afin de mettre à jour mon affichage, je ne sais pas si c'est la solution la plus optimale mais je pense qu'elle est largement mieux que le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    delete scene;
    Fond();
    Rectangles();
    que j'utilisais avant.
    Mon Animation.cpp ressemble désormais à çà:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    #include "Animation.h"
     
    Animation::Animation(int x, QWidget *parent = 0) : QDialog(parent)
    {
    	QColor couleur[] = {Qt::darkRed, Qt::cyan, Qt::magenta, Qt::gray, Qt::green, Qt::yellow, Qt::red, Qt::blue};
    	QPen pen(Qt::black, 1, Qt::SolidLine);
     
    	Fond();
     
    	for (int i = 0; i<x ; i++) {
    		tmp.taille = 100-(i*10);
    		tmp.in = couleur[i];
    		tour1.push_back(tmp);
    		tour1[i].item = scene->addRect(QRect(-150+(i*5), 100-(i*25), 100-(i*10), -25),pen,tour1[i].in);
    	}
     
    	hanoi(x, tour1, tour3, tour2);
    }
     
    void Animation::Fond() {
     
    	scene =  new QGraphicsScene(-200, -200, 400, 400);
     
    	QPen pen(Qt::black, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
     
     
    	base = scene->addLine(QLine(-150, 100, 150, 100), pen);
    	baton1 = scene->addLine(QLine(0, 100, 0, -100), pen);
    	baton2 = scene->addLine(QLine(100, 100, 100, -100), pen);
    	baton3 = scene->addLine(QLine(-100, 100, -100, -100), pen);
     
    	base->setZValue(-1); baton1->setZValue(-1); baton3->setZValue(-1); baton2->setZValue(-1);
     
    	QGraphicsView *vue = new QGraphicsView(scene, this);
    	vue->setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing);
    	vue->setGeometry(50, 50, 405, 405);v
    	vue->setStyleSheet("background-color: #FFFFFF");
     
    	setFixedSize(510,510);
     
    	quitter = new QPushButton("Quitter", this);
    	quitter->setGeometry(180, 480, 150, 20);
     
    	connect(quitter,SIGNAL(clicked()),this, SLOT(accept()));
    }
     
    void Animation::Rectangles() {
     
    	QPen pen(Qt::black, 1, Qt::SolidLine);
     
    	for (int i = 0; i<(int)tour1.size() ; i++) {
    		scene->removeItem(tour1[i].item);
    		tour1[i].item = scene->addRect(QRect(-100-(tour1[i].taille/2), 100-(i*25), tour1[i].taille, -25),pen,tour1[i].in);
    	}
    	for (int i = 0; i<(int)tour2.size() ; i++) {
    		scene->removeItem(tour2[i].item);
    		tour2[i].item = scene->addRect(QRect(0-(tour2[i].taille/2), 100-(i*25), tour2[i].taille, -25),pen,tour2[i].in);
    	}
    	for (int i = 0; i<(int)tour3.size() ; i++) {
    		scene->removeItem(tour3[i].item);
    		tour3[i].item = scene->addRect(QRect(100-(tour3[i].taille/2), 100-(i*25), tour3[i].taille, -25),pen,tour3[i].in);
    	}
    }
     
    void Animation::hanoi(int x, QVector<Rect> &t1, QVector<Rect> &t3, QVector<Rect> &t2){
     
    	if ( x > 0 ) {
    		hanoi(x-1, t1, t2, t3);
    		bouger(t1, t3);
    		hanoi(x-1, t2, t3, t1);
    	}
    }
     
    void Animation::bouger(QVector<Rect> &t1, QVector<Rect> &t3) {
     
    	t3.push_back(t1.back());
    	t1.pop_back();
     
    	Rectangles();
    }
    Qu'en pensez vous ? est ce une bonne solution ou celle-ci est trop coûteuse ?
    Si oui il ne me reste plus que cette gestion du temps que je n'arrive pas à gérer

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    248
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2008
    Messages : 248
    Par défaut
    Une solution facile mais non recommandée serai d'utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QCoreApplication::processEvents()
    Dans ton cas si tu appelles cette fonction à chaque étape de ton animation, ton affichage sera mis à jour correctement. Par contre, cette fonction n'est pas faite pour être appellée souvent et donc ton animation risque d'être lente si tu l'appelles très souvent. C'est pourquoi on t'as recommandé les threads.
    Un timer c'est probablement un compromis entre les 2 et donc ca reste meilleure mais bon si tu veux quelque chose de très facile ...

    Nehme

Discussions similaires

  1. comment integer une animation swf dans une page
    Par naili dans le forum Intégration
    Réponses: 7
    Dernier message: 18/09/2002, 18h54
  2. Comment ne pas rejouer une animation après un clic ?
    Par mmmmhhh dans le forum ActionScript 1 & ActionScript 2
    Réponses: 4
    Dernier message: 04/09/2002, 16h11
  3. [Composants][Animation] Lire une vidéo compressée
    Par femtosa dans le forum Composants VCL
    Réponses: 6
    Dernier message: 03/09/2002, 08h03
  4. Rx Controls Gif animés
    Par toufou dans le forum Composants VCL
    Réponses: 6
    Dernier message: 23/08/2002, 14h09
  5. Passage de parametre a une anim Flash 5
    Par debug dans le forum Intégration
    Réponses: 4
    Dernier message: 03/06/2002, 17h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo