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

Discussion :

QThread, signaux et slots

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 62
    Points : 28
    Points
    28
    Par défaut QThread, signaux et slots
    Bonjour, je vais vous exposer mon problème en détail.
    C'est surement assez simple mais je ne comprends pas.

    Alors voilà J'ai une classe MainWindow dérivant de QMainWindow
    J'ai une autre classe OptionWindow dérivant de QWidget
    Le constructeur de OptionWindow prend en argument églament une MainWindow
    ce qui me permettra d'avoir acces à ses attributs via des méthodes d'accesseurs.

    Ensuite les attributs :
    MainWindow possède un attribut QTextBrowser *qText.
    OptionWindow possède un attribut QPushButton *launchB et un attribut
    MainWindow *mainW;

    La OptionWindow apparait lorsque l'utilisateur dans le menu de la MainWindow clic sur un onglet "Calcul"
    Il doit alors rentrer des paramètres dans cette fenêtre et appuyer sur le bouton launchB pour lancer les calculs.
    J'ai donc connecter le bouton et à un SLOT calcule() de OptionWindow comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void OptionWindow::createActions()
    {
    	connect(launchB, SIGNAL(clicked()), this, SLOT(calcule()));
    }
    C'est dans ce SLOT calcule que j'aimerai lancer un thread faisant les calculs évidemment. Mais avant j'aimerais être capable de faire une chose plus simple.

    Pour l'instant le SLOT ce résume à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void OptionWindow::calcule()
    {
    	mainW->getQText()->append("Lancement des calculs...");
    }
    getQText() comme vous vous en doutez permet juste d'acceder au QTextBrowser de la MainWindow.

    Jusqu'ici tout va bien, cela marche et heureusement !

    Je peux maintenant vous donner mon problème de Thread, imaginons qu'au lieu de lancer des calculs je veuille juste un Thread qui puisse écrire dans le QTextBrowser de la MainWindow

    J'ai donc fait Une classe MyThread héritant de QThread dont voici le header :
    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
     
    #ifndef HEADER_MYTHREAD
    #define HEADER_MYTHREAD
     
    #include <QtCore\QThread>
    #include "MyThread.h"
    #include "MainWindow.h"
     
    class MyThread : public QThread
    {
        public:
              MyThread(MainWindow *mw, QObject* parent = NULL);
              virtual ~MyThread();
     
     
        public slots:
              virtual void run();
     
        signals:
    	  void ecrireInfo();
     
        private:
              MainWindow *mwThread;
     
    };
     
    #endif
    Et voici 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
     
    #include "MyThread.h"
     
    MyThread::MyThread(MainWindow* mw, QObject* parent):
    QThread(parent)
    {
           mwThread = mw;
    }
    MyThread::~MyThread()
    {
         exit();
         wait();
    }
     
    void MyThread::run()
    {
    	emit ecrireInfo();
    }
     
    void MyThread::ecrireInfo(){}
    Je peux donc ajouter des éléments dans mon SLOT calcule() de OptionWindow : (j'ai préalablement ajouter l'attribut MyThread *thread dans OptionWindow)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void OptionWindow::calcule()
    {
    	mainW->getQText()->append("Lancement des calculs...");
            thread = new MyThread(mainW);
            connect(thread, SIGNAL(ecrireInfo()), this, SLOT(ecrire()));
            thread->start();
    }
    Donc En principe qd je lance le thread avec start(), cela appelle le run qui lui même est censé envoyer le signal ecrireInfo() qui ne fait rien, c'est juste un SIGNAL et apelle un SLOT ecrire()

    Le slot ecrire est simple, il est dans la classe OptionWindow et fait juste

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void OptionWindow::ecrire()
    {
    	mainW->getQText()->append("TEST");
    }

    Mais voilà, rien ne se passe.

    Merci d'avance à qui prendra le temps de lire ce message.
    Je débute et je sais que cela doit paraitre bien naif et que c'est surement très simple.

  2. #2
    Membre éprouvé

    Profil pro
    Responsable logiciel
    Inscrit en
    Octobre 2010
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Responsable logiciel

    Informations forums :
    Inscription : Octobre 2010
    Messages : 223
    Points : 1 183
    Points
    1 183
    Par défaut
    Attention, l'objet QThread lui-même appartient au thread qui l'a créé et utilise la boucle d'événements de ce thread créateur (en l'occurrence le thread principal). Donc si tu veux des appels asynchrones de slots d'un thread à un autre, il faut un objet émetteur distinct transféré dans son thread par un moveToThread(). L'article ci-dessous montre la bonne façon de s'y prendre:
    http://qt-labs.developpez.com/thread...-movetothread/

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 62
    Points : 28
    Points
    28
    Par défaut
    Ok, javais lu quelquechose sur les moveToThread en cherchant mais je ne vois pas bien comment cela se mettrait en oeuvre dans mon code.
    Et est-la seule possibilité ?

  4. #4
    Membre éprouvé

    Profil pro
    Responsable logiciel
    Inscrit en
    Octobre 2010
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Responsable logiciel

    Informations forums :
    Inscription : Octobre 2010
    Messages : 223
    Points : 1 183
    Points
    1 183
    Par défaut
    Si tu veux faire appels signaux / slots dans le genre que tu décrit il me semble que oui.

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 62
    Points : 28
    Points
    28
    Par défaut
    J'ai modifier certaines choses, ce que je fais fonctionne.... mais cela continue de freeze la GUI... ça me donne vraiment envie d'utiliser les threads d'une autre lib bien que j'aurai aimé conserver Qt pour l'intégralité.

    J'ai pourtant l'impression de faire les choses correctement. Je résume :

    J'ai donc mon thread principal qui lance l'application graphique.
    J'ai une classe MyThread dérivée de QThread
    Et j'ai fait une classe Calculs dans laquelle se situe toutes mes fonctions de traitement calculs dérivant de QObject

    Dans la réimplémentation du run de MyThread
    je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void MyThread::run()
    {
         Calculs *obj_calculs = new Calculs()
         obj_calculs->moveToThread(this);
         obj_calculs->traitement();
    }
    Pour moi, je déplace l'objet obj_calculs dans le thread créé donc quand j'apelle la fonction traitement de mon objet censée faire les calculs en background, cela devrait se faire dans le nouveau thread. Pourtant tout freeze durant le temps de traitement...
    Je suis perdu

  6. #6
    Rédacteur

    Inscrit en
    Novembre 2006
    Messages
    1 272
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 272
    Points : 1 672
    Points
    1 672
    Par défaut
    Pour info tu l'utilises comment ta classe MyThread ?

  7. #7
    Membre éprouvé

    Profil pro
    Responsable logiciel
    Inscrit en
    Octobre 2010
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Responsable logiciel

    Informations forums :
    Inscription : Octobre 2010
    Messages : 223
    Points : 1 183
    Points
    1 183
    Par défaut
    http://qt.developpez.com/doc/latest/.../#movetothread

    C'est peut être que tu fais le modeToThread dans le run() du thread cible au lieu de le faire depuis le thread principal ...?

  8. #8
    Rédacteur

    Inscrit en
    Novembre 2006
    Messages
    1 272
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 272
    Points : 1 672
    Points
    1 672
    Par défaut
    Et aussi pour info pourquoi tu fais un moveToThread() ?
    Si tu l’enlève ça fait quoi ?

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 62
    Points : 28
    Points
    28
    Par défaut
    J'ai un attribut comme cela dans la classe OptionWindow faisant partie de la GUI
    Ensuite dans ma classe OptionWindow j'ai aussi un QPushButton appelé launch avec une QAction, quand on clic dessus, cela appelle un SLOT de OptionWindow appelé calcule().

    Dans ce SLOT calcule()
    j'émet un signal lancerCalcul(QString *) de la classe OptionWindow

    Et dans le constructeur de OptionWindow, j'ai connecté le Thread et ce dernier signal de la façon suivante :
    connect(this, SIGNAL(lancerCalcul(QString *)), &thread, SLOT(reception(QString *)));


    le SLOT reception(QString *) appartient à la classe Mythread donc et recoit un paramètre de nom de fichier a ouvrir pour faire les calculs...
    Et dans ce SLOT, j'apelle run() après vérif que le nom de fichier est correct.

  10. #10
    Rédacteur

    Inscrit en
    Novembre 2006
    Messages
    1 272
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 272
    Points : 1 672
    Points
    1 672
    Par défaut
    Juste pour info il ne faut jamais appeler run() à partir d'un Qthread mais start(). C'est start() qui lance le thread. A mon avis enlève le moveToThread et utilise start() et dis nous si cela change quelque chose.

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 62
    Points : 28
    Points
    28
    Par défaut
    J'ai tenté le moveToThread dans le thread principal, ca ne marchait pas...
    D'après ce que j'ai compris, le run d'un QThread A s'exécute dans le thread qui a créé A...
    Donc peut etre qu'il faudrait que je recrée un QThread B dans le run de A ?
    et que je fasse un B->moveToThread(A)
    ou A->moveToThread(B) je ne sais pas.

    Non ca ne change rien... mais c'est logique car mon thread est crée dans le main thread du coup son run est également exécuté dans le main thread.

    Il faut crée un 2ème thread ou déplacer le thread crée dans lui-même ? c'est tordu ...

    Bon si en fait la première méthode que j'avais donnée semble marcher...
    Il faut que je vois ca en détail.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void MyThread::run()
    {
         Calculs *obj_calculs = new Calculs()
         obj_calculs->moveToThread(this);
         obj_calculs->traitement();
    }

Discussions similaires

  1. Signaux et slots comme Qt
    Par b Oo dans le forum Qt
    Réponses: 21
    Dernier message: 11/04/2007, 17h57
  2. [Qt4] Signaux et Slot
    Par gentox dans le forum Qt
    Réponses: 9
    Dernier message: 25/01/2007, 18h35
  3. Réponses: 10
    Dernier message: 09/10/2005, 22h33

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