Un moveToThread() rebelle
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. :mrgreen:
Voici le fichier main.cpp
Code:
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:
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:
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:
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:
QObject::killTimer: timers cannot be stopped from another thread