Qt库事件循环问题
Posted
技术标签:
【中文标题】Qt库事件循环问题【英文标题】:Qt library event loop problems 【发布时间】:2010-12-19 16:14:02 【问题描述】:我正在编写一个 DLL,它被另一个应用程序用作插件,并希望利用 Qt 的功能。 我已经设置、编译和运行了所有类,但没有发出任何信号。 所以看起来好像没有QEventLoop。
尝试 1: 我将主类修改为子类 QThread 而不是 QObject,并在 run() 中创建一个 QEventLoop,连接所有信号/插槽,然后执行线程。 但是它没有说没有 QApplication 就不能拥有 QEventLoop。
尝试 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
【问题讨论】:
【参考方案1】:您必须创建一个 QCoreApplication 或 QApplication,并且您必须在主线程中进行。
这并不意味着您不能将代码放入插件中...除非应用程序始终在自己的线程中运行每个插件。
如果应用程序正在这样做,那么您可以尝试挂钩到应用程序使用的任何本机事件循环,并安排它在主线程中调用您插件中的某些函数。
【讨论】:
不幸的是,我无法在使用我的插件的主应用程序中进行任何操作,而且我只能在调用有限数量的函数(DLL 挂钩和几个注册函数)时执行代码.最重要的是,我不知道我的 DLL 是被主线程调用还是被插件管理线程调用。最糟糕的是,即使我在主线程空间中,当它通过我的控制权时,我也无法调用阻塞的 exec() 语句,因为我必须返回主应用程序才能运行。那么我绝对没有办法为非 Qt 3rd 方应用程序提供 Qt 库吗? 如果你找不到一个安全的方法来实例化一个 QCoreApplication 或 QApplication 那么你就不能使用大部分 Qt。不过,如果您找不到解决方案,我会感到惊讶——毕竟,您有一个 C++ 插件,可以在应用程序进程中执行任意代码。会有办法让它发挥作用。【参考方案2】:我已经成功创建了一个 QCoreApplication 并在后台线程上运行它。这不是标准实现,但可以用于简单的信号/插槽功能。我为具有大型遗留 Qt 代码库的原生 iOS 应用程序执行此操作。
//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 );
【讨论】:
以上是关于Qt库事件循环问题的主要内容,如果未能解决你的问题,请参考以下文章