problemi ciclo di eventi di libreria Qt
-
21-09-2019 - |
Domanda
Sto scrivendo una DLL che viene utilizzato come un plugin da un'altra applicazione e vorrebbe sfruttare le capacità di Qt.
Ho tutte le classi di set up, compilazione e l'esecuzione, ma non sono presenti segnali emessa.
Così sembra come se non c'è QEventLoop.
Tentativo 1:
Ho modificato la mia classe principale per creare una sottoclasse QThread invece di QObject, e nel run () creare un QEventLoop, collegare tutti i segnali / slot, ed exec il filo.
Ma non riesce dicendo che non si può avere un QEventLoop senza QApplication.
Tentativo 2:
Ho modificato la classe principale (ancora sottoclasse la QThraed) per istanziare invece un QCoreApplication, collegare tutti i segnali / slot, quindi exec l'applicazione.
Avverte che QApplication non è stato creato nel thread principale (), e ancora non emette segnali.
Non sono davvero sicuro di cosa fare qui. Io, ovviamente, non può creare una QCoreApplication nell'applicazione che utilizzerà il plug-in, e non posso emettere segnali senza uno.
Ho incluso un semplice (e orribilmente scritto) applicazione di test che dovrebbe illustrare il mio problema:
Qualsiasi aiuto sarebbe apprezzato!
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;
}
Output:
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
Soluzione
sono per creare un QCoreApplication o QApplication e sono per farlo nel thread principale.
Ciò non significa che non si può mettere il codice per che nel vostro plugin ... a meno che l'applicazione viene eseguita sempre ogni plugin nel proprio thread.
Se l'applicazione è di farlo, allora si può provare l'aggancio a qualsiasi ciclo di eventi nativo applicazione utilizza, e organizzare per chiamare una qualche funzione nel vostro plugin nel thread principale.
Altri suggerimenti
Ho avuto successo la creazione di un QCoreApplication e in esecuzione su un thread in background. Questo è non un'implementazione standard, ma può funzionare per funzionalità segnale / slot di semplice. Ho fatto questo per un iOS app nativa con una grande eredità base di codice 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();
});
I segnali sparati sullo stesso thread in cui sono stati collegati saranno catturati. Per catturare segnali su diversi thread è necessario creare e interrogare un QEventLoop sul thread in cui sono stati creati i segnali.
//Fire me periodically on the thread the signals and slots were connected
QEventLoop loop;
loop.processEvents( QEventLoop::ExcludeUserInputEvents, 500 );