在不同的线程中创建 QApplication
Posted
技术标签:
【中文标题】在不同的线程中创建 QApplication【英文标题】:creating QApplication in a different thread 【发布时间】:2014-08-17 12:14:44 【问题描述】:我正在尝试,但发现了 2 个主要问题:
1- 我无法与 GUI 交互
2- 一些警告:WARNING: QApplication was not created in the main() thread.
QObject::startTimer: timers cannot be started from another thread //happens when resizing widget
QObject::killTimer: timers cannot be stopped from another thread
这是完整的代码:(它可能有一些内存泄漏,但出于测试目的它失败了)
//main.cpp
#include <QCoreApplication>
#include "cthread.h"
int main(int argc, char *argv[])
CThread *MyThread = new CThread;
MyThread->start();
QCoreApplication a(argc, argv);
return a.exec();
//CThread.h
#ifndef CTHREAD_H
#define CTHREAD_H
#include <QThread>
#include "theqtworld.h"
class CThread : public QThread
Q_OBJECT
public:
CThread();
void run( void );
private:
TheQtWorld *mWorld;
;
#endif // CTHREAD_H
//CThread.cpp
#include "cthread.h"
#include <iostream>
CThread::CThread():mWorld(NULL)
void CThread::run()
std::cout << "thread started" << std::endl;
if(!mWorld)
mWorld = new TheQtWorld();
mWorld->OpenWorld();//now it will init all Qt Stuff inside
// if(mWorld) delete mWorld;
// emit this->exit();
//theqtworld.h
#ifndef THEQTWORLD_H
#define THEQTWORLD_H
#include <QObject>
#include "mainwindow.h"
#include <QApplication>
class TheQtWorld : public QObject
Q_OBJECT
public:
explicit TheQtWorld(QObject *parent = 0);
int OpenWorld(void);
signals:
public slots:
;
#endif // THEQTWORLD_H
//theqtworld.cpp
#include "theqtworld.h"
TheQtWorld::TheQtWorld(QObject *parent) :
QObject(parent)
int TheQtWorld::OpenWorld()
static int arg = 0;
static char *b[2];
b[0] = "a";
QApplication *a = new QApplication(arg, b);
a->setParent(this);
MainWindow w;
w.show();
return a->exec();
【问题讨论】:
为什么要在另一个线程中创建应用程序?我看不出有任何理由这样做,而且我很确定 Qt 不支持它。 整个工作流程将是另一个非 Qt 应用程序的插件,它有自己的事件系统,所以我不能在主线程中放置阻塞调用 有解决此问题的方法。定期调用QApplication::processEvents()
而不是调用QApplication::exec
可能会有所帮助。谷歌“qt 在另一个事件循环中集成”。另请参阅this。
@MohamedSakrAboYoucuf,您可以简单地使用 QThread!每个 QThread 都有不同的事件循环。您不需要新的 Q*Application 实例(Qt 不支持)来拥有新的 eventLopp
我在 main() 函数中有一个 QCoreApplication。仅允许使用 1 个 QCoreApplication 或其派生的实例(我使用 Q*Application 表示法)。 @MohamedSakrAboYoucuf 阅读 here 以了解如何使用 QThread 使用不同的 eventLoop
【参考方案1】:
在了解如何克服这个问题后,我会回答我自己的问题
首先问题是将 Qt GUI 作为插件集成到另一个应用程序中,因此主要问题是 Qt 事件与任何其他应用程序事件之间的事件循环冲突
我的第一个想法是将两者分开,因此 QApplication 将留在不同的线程,但这是一种完全错误的方法,这是我注意到的:
1- Qt GUI 必须留在 main() 线程so there is no other place for QApplication
2-为了避免阻塞 QApplication::exec()
,将 QApplication::processEvents()
嵌入到另一个应用程序事件循环中
这是一个工作代码:
//main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
QApplication mApp(argc, argv);
MainWindow w;
w.show();
//just for testing and holding the program so it doesn't end
for(int i = 0; i < 100000000; ++i)
mApp.processEvents();
return 0;
edit:感谢 pavel-strakhov 的出色建议。
【讨论】:
这不会消耗 100% cpu 吗? 对于这个测试“这么大的for循环,processEvents()
之间没有间隔”是的,它会让CPU保持忙碌,但是一旦你设置了间隔并美化了代码,你就可以在for中做其他事情loop "例如你可以做其他计算,这个for循环只是另一个应用程序的事件循环的表示"
如果主线程不可用,您有什么建议吗?我正在尝试将一些 GUI 调试窗口嵌入到非 qt 应用程序中。我尝试调试的应用程序部分不在主线程中运行。
@TomášZato 没关系,您需要从正在运行的线程中调用您的 Qt 应用程序,并使用 mApp.processEvents() 从那里进行控制;如上例以上是关于在不同的线程中创建 QApplication的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Cloud GCP pubsub 中创建特定于消息通道的线程