problemas de bucle de eventos biblioteca Qt
-
21-09-2019 - |
Pregunta
Estoy escribiendo un archivo DLL que se utiliza como un plugin por otra aplicación y le gustaría capacidades de apalancamiento de Qt.
Tengo todas las clases establecidas, compilar y ejecutar, pero no está emitiendo señales.
Por lo tanto, parece que no hay QEventLoop.
Intento 1:
He modificado mi clase principal subclase QThread en lugar de QObject, y en el run () crear un QEventLoop, conectar todas las señales / ranuras, y exec con el hilo.
Pero fracasa diciendo que no se puede tener un QEventLoop sin QApplication.
Intento 2:
He modificado la clase principal (siendo la subclasificación de la QThraed) para crear una instancia de un lugar QCoreApplication, conectar todas las señales / ranuras, a continuación, la aplicación exec.
Advierte que la QApplication no fue creado en el hilo principal (), y las señales todavía no emitirá.
No estoy muy seguro de qué hacer aquí. Obviamente no puedo crear un QCoreApplication en la aplicación que se utilice mi complemento, y no puedo emitir señales sin uno.
he incluido un simple (y horriblemente escrito) aplicación de prueba que deben ilustrar mi problema:
Cualquier ayuda se agradece!
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;
}
Salida:
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
Solución
Tienes para crear una QCoreApplication o QApplication y Tienes para hacerlo en el hilo principal.
Eso no significa que no se puede poner el código para que, en su plugin ... a menos que la aplicación siempre se ejecuta cada plugin en su propio hilo.
Si la aplicación es de hacer eso, entonces puede intentar enganchar a cualquier bucle de eventos nativa los usos de aplicaciones, y se encargará de esta una llamada a alguna función en su plugin en el hilo principal.
Otros consejos
He tenido éxito creando un QCoreApplication y ejecutarlo en un subproceso de fondo. Este es no una implementación estándar, pero puede trabajar para la funcionalidad de señal / ranura simple. Hice esto para una aplicación de iOS nativo con un legado de gran Qt código base.
//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();
});
Señales dispararon sobre el mismo hilo en el que estaban conectados, será atrapado. Para señales de agarre en diferentes hilos debe crear y sondear un QEventLoop en el hilo donde se crearon las señales.
//Fire me periodically on the thread the signals and slots were connected
QEventLoop loop;
loop.processEvents( QEventLoop::ExcludeUserInputEvents, 500 );