Bonsoir,

J'ai créé un petit projet avec Qt Creator pour apprendre à manipuler les threads avec QThread. Ce projet qui n'a qu'un but ludique consiste à créer une sorte de métronome dans un thread différent du thread principal. Jusque là, rien d'anormal.

Voici le fichier main.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
#include <QApplication>
 
#include "mygui.h"
#include "myclockwork.h"
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    MyGui gui;
    MyClockwork clockwork;
    app.connect(&clockwork, SIGNAL(tick()), &gui, SLOT(tick()));
    app.connect(&app, SIGNAL(aboutToQuit()), &clockwork, SLOT(stop()));
 
    gui.show();
    clockwork.start();
 
    return app.exec();
}
Comme on peut le voir, le métronome (classe MyClockwork) possède deux slots publics, start() et stop(), ainsi qu'un signal tick(). Par ailleurs, le slot stop() est appelé quand l'application est sur le point de quitter; le problème réside là.
Voici les fichiers liés à la classe du métronome:
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
#ifndef MYCLOCKWORK_H
#define MYCLOCKWORK_H
 
#include <QObject>
 
#include <QApplication>
#include <QThread>
#include <QTimer>
 
class MyClockwork : public QObject
{
    Q_OBJECT
 
    public:
        MyClockwork(QObject* parent = 0);
        ~MyClockwork();
 
    public slots:
        void start();
        void stop();
 
    signals:
        void tick();
 
    private:
        QThread* m_thread;
        QTimer* m_timer;
 
    private slots:
        void timerFired();
};
 
#endif // MYCLOCKWORK_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
#include "myclockwork.h"
 
MyClockwork::MyClockwork(QObject* parent) :
    QObject     (parent)        ,
    m_thread    (new QThread)   ,
    m_timer     (new QTimer)
{
    m_timer->setSingleShot(false);
}
 
MyClockwork::~MyClockwork()
{
    delete m_timer;
    delete m_thread;
}
 
void MyClockwork::start()
{
    m_timer->setInterval(1000);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(timerFired()), Qt::DirectConnection);
    m_timer->start();
    m_timer->moveToThread(m_thread);
    m_thread->start();
}
 
void MyClockwork::stop()
{
    if(m_thread->isRunning())
    {
        m_timer->moveToThread(QApplication::instance()->thread());
        m_thread->quit();
    }
    m_timer->stop();
    disconnect(m_timer, SIGNAL(timeout()), this, SLOT(timerFired()));
}
 
void MyClockwork::timerFired()
{
    emit tick();
}
Le problème est que, lorsque je renvoie le minuteur m_timer dans le thread principal via la commande m_timer->moveToThread(QApplication::instance()->thread()), je reçois l'erreur suivante:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
QObject::moveToThread: Current thread (0x3779a8) is not the object's thread (0x7262a0).
Cannot move to target thread (0x3779a8)
En gros, l'application ne parvient pas à mettre l'objet QTimer dans le thread-cible.
Pourquoi? Je ne sais pas; c'est pourquoi je sollicite votre aide.

Merci d'avance.

Adishatz!

PS: Quand l'application est terminée, j'obtiens aussi cette erreur:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
QObject::killTimer: timers cannot be stopped from another thread