создание QApplication в другом потоке

Я пытаюсь создать QApplication в другом потоке, но обнаружил 2 основные проблемы:
1- не могу взаимодействовать с графическим интерфейсом
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();
}

person Mohamed Sakr    schedule 17.08.2014    source источник
comment
Почему вы хотите создать приложение в другом потоке? Я не вижу причин для этого, и я почти уверен, что это не поддерживается Qt.   -  person Janick Bernet    schedule 17.08.2014
comment
весь рабочий процесс будет плагином для другого приложения, отличного от Qt, у которого есть собственная система событий, поэтому я не могу поместить блокирующий вызов в основной поток   -  person Mohamed Sakr    schedule 17.08.2014
comment
Есть обходные пути для этой проблемы. Периодический вызов QApplication::processEvents() вместо вызова QApplication::exec может помочь. Google qt интегрируется в другой цикл событий. См. также это.   -  person Pavel Strakhov    schedule 17.08.2014
comment
@PavelStrakhov это именно то, что я хотел :), я думал, что основное решение состоит в том, чтобы поместить каждый цикл событий в отдельный поток, чтобы они не сталкивались, но это решение отправки событий неблокирующим вызовом функции намного лучше   -  person Mohamed Sakr    schedule 17.08.2014
comment
@MohamedSakrAboYoucuf, вы можете просто использовать QThread! Каждый QThread имеет свой цикл обработки событий. Вам не нужен новый экземпляр Q*Application (не поддерживается Qt), чтобы иметь новый eventLopp   -  person Massimo Costa    schedule 17.08.2014
comment
@MassimoCosta Это не новый QApplication, это единственный QApplication.   -  person Oktalist    schedule 17.08.2014
comment
У меня есть QCoreApplication в функции main(). Разрешен только 1 экземпляр QCoreApplication или его производного (я использовал нотацию Q*Application). @MohamedSakrAboYoucuf прочитайте здесь, чтобы понять, как использовать различные циклы событий, используя QThread   -  person Massimo Costa    schedule 17.08.2014
comment
@MassimoCosta * QApplication - это просто член, который инициализируется один раз, и я заметил проблемы в этом подходе. Мне нужен только 1 базовый экземпляр семейства QApplication, и я ДОЛЖЕН использовать основной поток для графического интерфейса, поэтому QApplication   -  person Mohamed Sakr    schedule 17.08.2014


Ответы (1)


Я бы ответил на свой вопрос после того, как понял, как решить эту проблему.

сначала проблема заключалась в том, чтобы интегрировать графический интерфейс Qt в качестве плагина в другое приложение, поэтому основной проблемой было столкновение цикла событий между событиями Qt и любыми другими событиями приложения.

моей первой мыслью было разделить оба, поэтому QApplication останется в другом потоке, но это был совершенно неправильный подход, и вот что я заметил:

1- Графический интерфейс Qt должен оставаться в потоке 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;
}

редактировать: спасибо pavel-strakhov за его отличное предложение.

person Mohamed Sakr    schedule 17.08.2014
comment
не будет ли это потреблять 100% процессор? - person paulm; 17.08.2014
comment
для этого теста этот большой цикл for и отсутствие интервалов между processEvents() да, это будет загружать ЦП, но как только вы установите интервалы и украсите код, вы можете делать другие вещи в цикле for, например, вы можете выполнять другие вычисления, этот цикл for это просто представление цикла событий другого приложения - person Mohamed Sakr; 17.08.2014
comment
Есть ли у вас какие-либо советы, если основной поток недоступен? Я пытаюсь встроить окно отладки GUI в приложение, отличное от qt. Часть приложения, которую я пытаюсь отладить, не запускается в основном потоке. - person Tomáš Zato - Reinstate Monica; 26.04.2017
comment
@TomášZato, это не имеет значения, вам нужно будет вызывать приложение Qt из работающего потока и управлять оттуда с помощью mApp.processEvents(); как в примере выше - person Mohamed Sakr; 26.04.2017