Проблемы цикла событий библиотеки Qt
Я пишу DLL, которая используется в качестве плагина другим приложением и хотела бы использовать возможности Qt.
У меня все классы настроены, компилируются и работают, но сигналы не передаются. Таким образом, кажется, что нет никакого QEventLoop.
Попытка 1:
Я изменил свой основной класс на подкласс QThread вместо QObject и в run() создал QEventLoop, соединил все сигналы / слоты и выполнил поток.
Но он не говорит о том, что у вас не может быть QEventLoop без QApplication.
Попытка 2:
Я изменил основной класс (все еще подкласс QThraed), чтобы вместо этого создать экземпляр QCoreApplication, подключить все сигналы / слоты, а затем выполнить приложение.
Предупреждает, что приложение QApplication не было создано в потоке main() и по-прежнему не будет излучать сигналы.
Я не совсем уверен, что делать здесь. Я, очевидно, не могу создать приложение QCoreApplication, которое будет использовать мой плагин, и я не могу излучать сигналы без него.
Я включил простое (и ужасно написанное) тестовое приложение, которое должно проиллюстрировать мою проблему:
Любая помощь будет оценена!
main.cpp:
#include <iostream>
#include "ThreadThing.h"
using namespace std;
int main(int argc, char *argv[])
{
cout << "Main: " << 1 << endl;
ThreadThing thing1;
cout << "Main: " << 2 << endl;
thing1.testStart();
cout << "Main: " << 3 << endl;
thing1.testEnd();
cout << "Main: " << 4 << endl;
thing1.wait(-1);
cout << "Main: " << 5 << endl;
return 0;
}
ThreadThing.h:
#ifndef THREADTHING_H
#define THREADTHING_H
#include <QThread>
class ThreadThing : public QThread
{
Q_OBJECT
public:
ThreadThing();
virtual void run();
void testStart();
void testEnd();
public slots:
void testSlot();
signals:
void testSignal();
};
#endif//THREADTHING_H
ThreadThing.cpp:
#include "ThreadThing.h"
#include <iostream>
#include <QCoreApplication>
using namespace std;
ThreadThing::ThreadThing()
{
cout << "Constructor: " << 1 << endl;
this->start();
cout << "Constructor: " << 2 << endl;
}
void ThreadThing::run()
{
cout << "Run: " << 1 << endl;
int i = 0;
cout << "Run: " << 2 << endl;
QCoreApplication* t = new QCoreApplication(i, 0);
cout << "Run: " << 3 << endl;
connect(this, SIGNAL(testSignal()), this, SLOT(testSlot()), Qt::QueuedConnection);
cout << "Run: " << 4 << endl;
t->exec();
cout << "Run: " << 5 << endl;
}
void ThreadThing::testStart()
{
cout << "TestStart: " << 1 << endl;
emit testSignal();
cout << "TestStart: " << 2 << endl;
}
void ThreadThing::testEnd()
{
cout << "TestEnd: " << 1 << endl;
this->quit();
cout << "TestEnd: " << 1 << endl;
}
void ThreadThing::testSlot()
{
cout << "TEST WORKED" << endl;
}
Выход:
Main: 1
Constructor: 1
Constructor: 2
Main: 2
TestStart: 1
TestStart: 2
Main: 3
TestEnd: 1
TestEnd: 1
Main: 4
Run: 1
Run: 2
WARNING: QApplication was not created in the main() thread.
Run: 3
Run: 4
2 ответа
Вы должны создать QCoreApplication или QApplication и сделать это в основном потоке.
Это не значит, что вы не можете поместить код для этого в свой плагин... если приложение не запускает каждый плагин в своем собственном потоке.
Если приложение делает это, то вы можете попробовать подключиться к любому собственному циклу событий, который использует приложение, и организовать для него вызов некоторой функции в вашем плагине в главном потоке.
Я успешно создал QCoreApplication и запустил его в фоновом потоке. Это не стандартная реализация, но может работать для простой функциональности сигнал / слот. Я сделал это для родного приложения iOS с большой устаревшей кодовой базой Qt.
//I really don't do anything but run on a background thread
class MyQtAppForBackgroundThread : public QCoreApplication
{
Q_OBJECT
...
}
//iOS specific code here...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^(void){
// This spawns a QCoreApplication on a background thread in an attempt to create something that can
// queue signals across threads
qtApp = new MyQtAppForBackgroundThread(smArgc, smArgv);
qtApp->exec();
});
Сигналы, запущенные в том же потоке, где они были подключены, будут перехвачены. Чтобы поймать сигналы в разных потоках, вы должны создать и опросить QEventLoop в потоке, в котором были созданы сигналы.
//Fire me periodically on the thread the signals and slots were connected
QEventLoop loop;
loop.processEvents( QEventLoop::ExcludeUserInputEvents, 500 );