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

Multithreading Discussion :

Thread et widget 3D


Sujet :

Multithreading

  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 129
    Par défaut Thread et widget 3D
    Bonjour,

    Je réalise une application multiThread et ces derniers me posent encore des problèmes. Alors voilà :

    J'ai une fenêtre réalisée avec Qt Creator, dérivant donc de MainWindow. Cette fenêtre comporte un GLWidget et plein d'autres Widgets. On manipule le rendu GL avec tous les autres petits widgets.
    Mais voila, j'ai besoin de lancer une animation (succession d'images générées par le GLWidget) en cliquant sur un bouton, et étant donné que le rendu est suffisemment rapide, j'ai créé un Thread qui se charge de faire un wait entre chaque image. Mais voilà, tout s'affiche dans mon GLWIdget une fois l'animation terminée et entre temps, toute l'application est figée alors que chaque image devrait s'afficher tous les 250 millisecondes, je ne vois pas comment palier le problème...

    Voici mon code :
    Ci-dessous le constructeur de ma fenêtre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Window3D::Window3D()
    {
        // Creation du widget 3d une fois la table créée
        m_widget3d = new GLWidget();
        m_widget3d->show();
     
        // Démarrage du Thread
        m_thread3d = new Thread3D(m_widget3d, nb_images);
        connect(m_thread3d, SIGNAL(send_to_widget(int)), m_widget3d, SLOT(load_image(int)));
    }
    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
     
    void Thread3D::Animation(int index)
    {
        int ind_current_image = index;
     
        while(ind_current_image <= nb_images )
        {
            cout << "write image " << ind_current_date << endl;
     
            emit send_to_widget(++ind_current_image);
            int ms = 250;
            #ifdef Q_OS_WIN
                Sleep(uint(ms));
            #else
                struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
                nanosleep(&ts, NULL);
            #endif
        }
    }
    Il semble que je n'aie donc toujours pas avalé la théorie avec les threads. Je pensais qu'en faisant son sleep, le thread laissait la main au widget3d qui peut alors dessiner ce qu'il a à dessiner. Or tout est bloqué... Je n'ai évidememnt plus acces aux autres fonctionnalités 3D et la Window3D est freezée le temps que la boucle de animation se termine...

    Je ne sais pas trop comment arranger ce petit problème... J'ai essayé de créer un objet Sender, instancié par le Thread, qui se charge d'envoyer le signal au widget3d pour lui dire de se recharger, mais il n'en est rien...

    Quelqu'un aurait-il une idée ?

    Merci d'avance

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Bonjour

    J'ai lu en diagonal, mais la question a été abordée dans un article : http://qt-labs.developpez.com/thread/opengl-qt48/
    Cela peut aider ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 129
    Par défaut
    Et bien, je n'y ai pas franchement trouvé ma solution. Le seul paragraphe qui pourrait m'aider est le troisième et puis non, je ne trouve même pas que mon problème soit identique. Ce n'est pas mon GPU qui bloque, c'est mon Thread Fils. Le principal et le GPU sont en attente de ce dernier alors que théoriquement, un parralélisme devrait s'opérer. J'ai tout de même essayé en utilisant les fonctions doneCurrent() et makeCurrent(), mais c'est pas franchement clair, jvois pas vraiment ou les utiliser, et le thread d'échange, késako ? un troisième Thread qui permet de faire communiquer le Thread principal et le(s) fils ? De toute manière, je n'ai besoin que d'un seul contexte OpenGL. Non franchement, l'article m'a pas aidé, mais je suis certain que le problème vient de moi.

  4. #4
    Membre éclairé
    Inscrit en
    Mars 2011
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Mars 2011
    Messages : 50
    Par défaut
    Je m'avance peut-être un peu mais c'est de l'attente active ton sleep non ?
    Pourquoi ne pas passer par des timer ? (qui sont généralement utilisé pour les animations)
    Sinon tu reçois bien le signal ?
    Si tu envoie une seule image ton thread se termine correctement ?

  5. #5
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Citation Envoyé par 0_Azerty_0 Voir le message
    Et bien, je n'y ai pas franchement trouvé ma solution. Le seul paragraphe qui pourrait m'aider est le troisième et puis non, je ne trouve même pas que mon problème soit identique. Ce n'est pas mon GPU qui bloque, c'est mon Thread Fils. Le principal et le GPU sont en attente de ce dernier alors que théoriquement, un parralélisme devrait s'opérer. J'ai tout de même essayé en utilisant les fonctions doneCurrent() et makeCurrent(), mais c'est pas franchement clair, jvois pas vraiment ou les utiliser, et le thread d'échange, késako ? un troisième Thread qui permet de faire communiquer le Thread principal et le(s) fils ? De toute manière, je n'ai besoin que d'un seul contexte OpenGL. Non franchement, l'article m'a pas aidé, mais je suis certain que le problème vient de moi.
    Normal, je me suis trompé de tuto...
    http://qt-quarterly.developpez.com/q...imension/#LIII

    Sinon, j'ai pas compris pourquoi tu veux threader. Si ton rendu est plus rapide que tes FPS, tu n'as pas de problème

    Sinon, un autre tuto pour QtOpenGL : http://gbelz.developpez.com/remi-ach...vance-avec-qt/

    Et dans ton code, tu n'expliques pas comment la fonction Animation est appelée

  6. #6
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 129
    Par défaut
    Je m'avance peut-être un peu mais c'est de l'attente active ton sleep non ?
    Pourquoi ne pas passer par des timer ? (qui sont généralement utilisé pour les animations)
    Sinon tu reçois bien le signal ?
    Si tu envoie une seule image ton thread se termine correctement ?
    Non, le sleep n'est pas de l'attente active. On parle d'attente active lorsque l'on boucle sur une condition en vue d'effectuer une tâche lorsque la condition est remplie. en l'occurence, je me contente de faire un sleep entre chaque image.

    Bien sur j'ai pensé aux QTimer et j'ai même commencé par là, mais le problème c'est que je peux pas connecter mon Timer à ma fonction puisque je dérive pas de QObject. (s'il y a une solution à ce problème, sans dériver de QObject, je suis preneur, sinon, c'est ce que j'ai finir par faire à court terme afin d'avoir une solution "qui tourne", mais bon, je vise aussi la cohérence du programme.

    Sinon, j'ai pas compris pourquoi tu veux threader. Si ton rendu est plus rapide que tes FPS, tu n'as pas de problème
    Et bien, je dois tourner à 200 fps par défaut, mais j'ai tout de même un peu de traitement pour générer chaque image, et quand bien même je garde mes 200 fps, ce qu'il se passe, c'est que je clique sur le bouton Animation (c'est lui qui appelle la fonction Animation avec son signal clicked, réimplémenté pour l'occasion), l'image se fige jusqu'à ce que le traitement soit terminé et bim, si j'ai 200 images, je passe directement à la dernière image sans avoir visualisé les autres. Je pensais que le Thread débloquerait tout ca...

    merci pour les tutaux, j'ai tellement de liens que jfinis par en zapper !

  7. #7
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Citation Envoyé par 0_Azerty_0 Voir le message
    Bien sur j'ai pensé aux QTimer et j'ai même commencé par là, mais le problème c'est que je peux pas connecter mon Timer à ma fonction puisque je dérive pas de QObject. (s'il y a une solution à ce problème, sans dériver de QObject, je suis preneur, sinon, c'est ce que j'ai finir par faire à court terme afin d'avoir une solution "qui tourne", mais bon, je vise aussi la cohérence du programme.
    Quelle fonction ? Tes classes dérivent de QObject donc tu peux utiliser les slots, non ?

    Citation Envoyé par 0_Azerty_0 Voir le message
    Et bien, je dois tourner à 200 fps par défaut, mais j'ai tout de même un peu de traitement pour générer chaque image, et quand bien même je garde mes 200 fps, ce qu'il se passe, c'est que je clique sur le bouton Animation (c'est lui qui appelle la fonction Animation avec son signal clicked, réimplémenté pour l'occasion), l'image se fige jusqu'à ce que le traitement soit terminé et bim, si j'ai 200 images, je passe directement à la dernière image sans avoir visualisé les autres. Je pensais que le Thread débloquerait tout ca...
    Si tu appelles updateGL() à chaque fois que tu as finis le calcul d'une image, ça ne pose pas de problème
    Regarde comment je fais : http://gbelz.developpez.com/remi-ach...roduction#L2-E

  8. #8
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 129
    Par défaut
    Excuse moi,

    J'ai vraiment manqué de donner des informations ! En fait, j'ai ma fenêtre 3D, qui contient mon QGLWidget et ce dernier contient une troisième classe qui gère toute l'information. C'est cette troisième classe qui réalise le traitement pour générer chaque image.

    la fonction appelée par le timer est donc load_image().

    Or cette troisième classe n'est pas dérivée de QObject. mais au final c'est ce que j'ai fait. C'est pas forcément cohérent ou "logique" puisque cette classe n'a pas lieu d'être un QObject, mais ca me facilite vraiment la vie là ! Donc voilà, merci beaucoup.

    PS : Je suis curieux de savoir tiens, je viens d'expliquer comment j'avais concu mon programme, mais est-ce qu'il y a une "bonne" habitude pour coder avec Qt et OpenGL ?

    je trouve ca franchement crade de tout mettre dans le GLWidget et de se retrouver avec des fichiers de centaines voir milliers de lignes. Pour ma part, je parse au maximum, je sais que certains mettent toutes leurs données dans une classe et font le traitement dans une autre pour seulement réaliser l'affichage dans une troisième qui est le GLWidget... Tu en penses quoi ?

  9. #9
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Non, c'est pas un problème d'avoir ta fonction de génération dans une classe non QObject.
    Par contre, il faut avoir une fonction "generate_next_image()" plutot qu'une fonction qui génère toutes les images

    Il y a une raison particulière de garder en mémoire toutes images ?

  10. #10
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 129
    Par défaut
    Bah c'est un peu ca en fait. Ma fonction generate_next_image(), je lui passe un numéro d'image et elle se débrouille avec. Par ailleurs, je conserve pas toutes mes images en mémoire, mais a chaque appel de la fonction, je recaclule les modifications (des couleurs de texture accessoirement)

  11. #11
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Citation Envoyé par 0_Azerty_0 Voir le message
    Bah c'est un peu ca en fait. Ma fonction generate_next_image(), je lui passe un numéro d'image et elle se débrouille avec. Par ailleurs, je conserve pas toutes mes images en mémoire, mais a chaque appel de la fonction, je recaclule les modifications (des couleurs de texture accessoirement)
    Donc tu connectes ton timer à un slot qui génère l'image suivante et tu l'affiches

  12. #12
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 129
    Par défaut
    Tout à fait, mais j'ai du transformer ma classe pour la faire dériver de QObject pour l'occasion, jtrouve ca un peu dommage. J'ai essayé de caster l'objet pour contourner le problème mais ca n'a pas fonctionné

    EDIT : Merci

  13. #13
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Citation Envoyé par 0_Azerty_0 Voir le message
    Tout à fait, mais j'ai du transformer ma classe pour la faire dériver de QObject pour l'occasion, jtrouve ca un peu dommage. J'ai essayé de caster l'objet pour contourner le problème mais ca n'a pas fonctionné

    EDIT : Merci
    Je comprend pas très bien pourquoi
    Voila ce que je te disais de faire :

    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
    class GLWidget : public QGLWidget {
        GLWidget::GLWidget() {
            QTimer timer;
            connect(timer, SIGNAL(tic tac toc), this, SLOT(updateImage());
        }
     
    private slots:
        void updateImage() {
            QImage img = render.generate(id);
            drawImage(img);
        }
     
    private:
        unsigned id;
        ImageRender render;
    };
     
    class ImageRender { // pas besoin d'héritage de QObject
        QImage generate(unsigned id) { bla bla bla }
    };

  14. #14
    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
    Il te manque Q_OBJECT :p

  15. #15
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Il me manque aussi le public, SIGNAL(tic tac toc) marchera pas, timer sera détruit en sortant du constructeur, connect prend un pointeur, etc.
    c'est pas un code compilable, juste un code d'illustration...

  16. #16
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 129
    Par défaut
    c'est pas un code compilable, juste un code d'illustration...
    De toute manière, je l'aurais pas copié ! Jsuis newbie, mais quand même, ya des limites !

    Mais oui, tu as complètement raison, dans l'idée c'est complètement faisable après, ca me demande quelques modifs, j'essayerai demain !
    Dans tous les cas, j'ai vraiment du mal avec les Threads. Toute la théorie que l'on peut apprendre à l'école n'a d'utilité sans de bons exemples concrets.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Thread, widget et mainwindow
    Par cover70 dans le forum Multithreading
    Réponses: 2
    Dernier message: 15/01/2013, 09h53
  2. Gestion de l'état des widgets Tkinter par des Threads
    Par piokml dans le forum Général Python
    Réponses: 3
    Dernier message: 18/10/2012, 11h00
  3. Widgets must be created in the GUI thread
    Par gassi64 dans le forum Qt
    Réponses: 8
    Dernier message: 29/06/2009, 14h46
  4. [SWT] synchro widget avec thread
    Par TiTiSeb dans le forum SWT/JFace
    Réponses: 7
    Dernier message: 08/09/2008, 21h21
  5. [gtkmm] thread et protection des widget
    Par Rniamo dans le forum GTK+
    Réponses: 7
    Dernier message: 15/08/2008, 17h27

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