QApplication在非主线程中

时间:2010-05-09 19:16:26

标签: c++ user-interface qt qt4

我需要在一个非主要的线程中执行()一个QApplication(我的GUI必须是可以在运行时动态加载和卸载的插件,因此我无法访问主线程)。有没有人知道(相对)无痛的方式来解决Qt限制在主要之外启动QApplication的问题?

我正在使用gcc4.3.4在C ++中使用Qt4在Linux中开发。

6 个答案:

答案 0 :(得分:8)

您可以在PThread中启动QApplication,如下所示

// main.cpp中

#include <iostream>
#include "appthread.h"
int main(int argc, char *argv[]) {
  InputArgs args = {argc, argv};
  StartAppThread(args);
  sleep(10);
  return 0;
}

// appthread.h

struct InputArgs{
  int argc;
  char **argv;
};
void StartAppThread(InputArgs &);

// appthread.cpp

#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include "appthread.h"
#include <pthread.h>

void *StartQAppThread(void *threadArg) {
  InputArgs *args = (struct InputArgs*) threadArg;
  QApplication app(args->argc, args->argv);
  QMainWindow w;
  w.show();
  w.setCentralWidget(new QPushButton("NewButton"));
  app.exec();
  pthread_exit(NULL);
}

void StartAppThread(InputArgs &args) {
  pthread_t thread1;  
  int rc = pthread_create(&thread1, NULL, StartQAppThread, (void*)&args);
}

答案 1 :(得分:4)

如果你正在使用QThread,那么你已经有了正常的Qt事件循环,并且可以在QThread :: run()函数中运行exec()。虽然您无法使用主线程之外的GUI对象,但您仍然可以通过排队的信号/插槽连接与它们进行交互。也许您可以尝试存储指向主线程QThread对象的指针,并调用QObject :: moveToThread()将GUI对象移动到主线程,而不是将QApplication移动到另一个线程中。

我认为尝试使用不同类型的hack和kluges反对工具包并不是一个好主意。

答案 2 :(得分:2)

Patch Qt,我猜并删除主线程检查,并测试它是否适合您。 根据 http://bugreports.qt-project.org/browse/QTBUG-7393 但是,这不适用于OS X / Cocoa,因为Cocoa假设第一个线程产生为主/ UI线程。

答案 3 :(得分:1)

好的,我有一些有用的东西!它并不漂亮,但绝对可以胜任。

  1. 创建一个包含所有实际GUI代码的QMainWindow衍生产品,并重载此类的event()函数以调用this-&gt; show()

  2. 创建一个类(让我们称之为Runner),它将保存一个指向QMainWindow派生的指针,并给它一个运行函数。

  3. 在Runner :: Runner()中,启动一个调用Runner :: run()的线程

  4. 在Runner :: run()(现在运行在它自己的线程中)构造一个QApplication,以及QMainWindow派生的实例化。调用QApplication的exec()函数。

  5. 现在,当你想启动你的GUI时,只需将任何事件发布到你的QMainWindow派生物上,它就会显示出来!

  6. 这个解决方案似乎在Linux中运行得很好,虽然它似乎正在利用Qt中的一些漏洞而且可能无法在其他平台上运行。绝对比修补Qt容易。

答案 4 :(得分:1)

将2美分加上花哨的lambda和C ++线程:

#include "mainwindow.h"
#include <QApplication>
#include <thread>

int main(int argc, char *argv[])
{
    std::thread t1
    (
        [&]
        {
            QApplication a(argc, argv);
            qInstallMessageHandler(MainWindow::qtMessageOutput);
            MainWindow w;
            w.show();
            return a.exec();
        }
    );
    t1.join();
}

这里Mainwindow是您的QMainWindow

答案 5 :(得分:0)

一个好的解决方案位于:git@github.com:midjji / convenient_multithreaded_qt_gui.git

然后仅是

run_in_gui_thread(new RunEventImpl([](){
        QMainWindow* window=new QMainWindow();
        window->show();
    }));

或您希望在gui线程中运行的任何代码。

随时可以在任何线程中调用,同时还要在bg中为您进行设置。