Добрый день! Подскажите пожалуйста, кто работал с QThread, каким образом сделать так, чтобы сигналы объекта обрабатывались пользовательским потоком, а не потоком графического интерфейса. Вот у Шлее есть 2 примера:
Первый:
#include <QtGui>
// ======================================================================
class MyThread : public QThread {
Q_OBJECT
private:
int m_nValue;
public:
MyThread() : m_nValue(10)
{
}
void run()
{
QTimer timer;
connect(&timer, SIGNAL(timeout()), SLOT(slotNextValue()));
timer.start(1000);
exec();
}
signals:
void finished ( );
void currentValue(int);
public slots:
void slotNextValue()
{
emit currentValue(--m_nValue);
if (!m_nValue) {
emit finished();
}
}
};
// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QLCDNumber lcd;
MyThread thread;
QObject::connect(&thread, SIGNAL(currentValue(int)),
&lcd, SLOT(display(int))
);
QObject::connect(&thread, SIGNAL(finished()),
&app, SLOT(quit())
);
lcd.setSegmentStyle(QLCDNumber::Filled);
lcd.display(10);
lcd.resize(220, 90);
lcd.show();
thread.start();
return app.exec();
}
#include "main.moc"
#include <QtGui>
// ======================================================================
class MyThread : public QThread {
Q_OBJECT
private:
int m_nValue;
public:
MyThread() : m_nValue(10)
{
}
void run()
{
exec();
}
signals:
void finished ( );
void currentValue(int);
public slots:
void slotNextValue()
{
emit currentValue(--m_nValue);
if (!m_nValue) {
emit finished();
}
}
};
// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QLCDNumber lcd;
MyThread thread;
QObject::connect(&thread, SIGNAL(currentValue(int)),
&lcd, SLOT(display(int))
);
QObject::connect(&thread, SIGNAL(finished()),
&app, SLOT(quit())
);
QTimer timer;
QObject::connect(&timer, SIGNAL(timeout()), &thread, SLOT(slotNextValue()));
// timer.moveToThread(&thread);
timer.start(1000);
lcd.setSegmentStyle(QLCDNumber::Filled);
lcd.display(10);
lcd.resize(220, 90);
lcd.show();
thread.start();
return app.exec();
}
#include "main.moc"
Есть замечательное правило, слот выполняется в том потоке, в котором был создан его объект.
Другими словами тебе нужно, чтобы объект слота slotNextValue создавался в потоке MyThread.
тут почитай: http://crossplatform.ru/documentation/qtdoc4.3/threads.php#signals-and-slots-across-threads
если я правильно понял вопрос, то должно быть так ( не тестил ):
// свой объект, слоты которого обрабатываются в рабочем потоке
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject( ) : m_nValue(10){ };
signals:
// сигнал о изменении значения.
void currentValue(int);
void wantQuit( );
public slots:
void slotNextValue()
{
emit currentValue(--m_nValue);
if (!m_nValue) {
emit wantQuit( );
}
}
private:
int m_nValue;
};
// ======================================================================
class MyThread : public QThread {
Q_OBJECT
public:
MyThread()
{
}
void run()
{
MyObject myObj( this );
connect( &myObj, SIGNAL( currentValue( int ) ), SIGNAL( currentValue( int ) ) );
connect( &myObj, SIGNAL( wantQuit( ) ), SLOT( quit( ) ) );
QTimer timer;
connect(&timer, SIGNAL(timeout()), &myObj, SLOT(slotNextValue()));
timer.start(1000);
exec();
}
signals:
void currentValue(int);
};
// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QLCDNumber lcd;
MyThread thread;
QObject::connect(&thread, SIGNAL(currentValue(int)),
&lcd, SLOT(display(int))
);
QObject::connect(&thread, SIGNAL(finished()),
&app, SLOT(quit())
);
lcd.setSegmentStyle(QLCDNumber::Filled);
lcd.display(10);
lcd.resize(220, 90);
lcd.show();
thread.start();
return app.exec();
}
#include "main.moc"
Вообщем ситуация с потоками слотами в них такая.
Для того чтобы поток мог отрабатывать сигналы от других потоков (что одно и то же - обработка сигналов и слотов объектов в которых находятся объекты ) НЕОБХОДИМО:
1. в поток добавить QEventLoop - это основной механизм через который идет передача сообщений QEvent's а сигналы реализованы как раз с помощью них
зы можно сделать локальной переменной в методе run а можно и членом класса - на выбор
2. сам поток необходимо поместить сам в себя т.е. сделать в конструкторе this->moveToThread(this);
3. реализовать м методе run что-то вроде этого
void T_SlotThread::run( )
{
fInnerLoop = new QEventLoop;
fInnerLoop->exec();
}
Есть небольшой вопросик на счет QEventLoop! Прочитал про этот класс в хелпе и не понял его предназначения, можете пояснить своими словами, пожалуйста? Предназначен обработки в цикле событий или что?
я особо не читал, но по моему мнению этот класс служит для организации циклов событий, управления ими, т.е. можно вообще например, выключить события и, например, при нажатии на клавишу ничего не будет происходить. Но это лишь мое мнение, точно не знаю
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)