Qt库事件循环问题

5
我正在编写一个DLL,作为另一个应用程序的插件,并希望利用Qt的能力。我已经设置好了所有类,进行编译和运行,但没有任何信号被发射出来。因此似乎没有QEventLoop。
尝试1:我修改了我的主类,将其子类化为QThread,然后在run()中创建一个QEventLoop,连接所有信号/槽,并执行线程。但它失败了,说你不能没有QApplication就有QEventLoop。
尝试2:我修改了主类(仍然是QThread的子类),改为实例化QCoreApplication,连接所有信号/槽,然后执行应用程序。警告说QApplication没有在main()线程中创建,并且仍然无法发射信号。
我不太确定该怎么办。显然,我无法在将使用我的插件的应用程序中创建QCoreApplication,也无法在没有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个回答

5

您必须创建一个QCoreApplication或者QApplication并且在主线程中进行。

这并不意味着不能将代码放在插件中...除非应用程序总是在每个插件中的独立线程中运行。

如果应用程序是这样做的,那么您可以尝试钩入应用程序使用的任何本地事件循环,并安排它在主线程中调用插件中的某些函数。


很不幸,我无法触及使用我的插件的主应用程序中的任何内容,而且只有在它调用有限数量的函数(DLL钩子和一些已注册的函数)时才能执行代码。更糟糕的是,我不知道我的DLL是由主线程还是插件管理线程调用的。 最糟糕的是,即使我在主线程空间中,当它将控制权传递给我时,我也不能调用阻塞的exec()语句,因为我必须返回以使主应用程序正常运行。 那么,我是否绝对没有办法为非Qt第三方应用程序创建Qt库? - Marc
如果您找不到一种安全的实例化QCoreApplication或QApplication的方法,那么您将无法使用Qt的大部分功能。不过,我相信您肯定能够找到解决方案 - 毕竟,您有一个C++插件,可以在应用程序进程中执行任意代码。总会有办法让它正常工作的。 - rohanpm

1

我成功创建了一个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 );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接