如何在主线程外创建 QtQuick window

How to create QtQuick window outside the main thread

我想要的是一个主线程,它实例化一个扩展 QQuickView 并将其移动到第二个线程的 class。

理想情况下,我想做这样的事情:

main.cpp

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    MyClass myClassObj;

    myClassObj.init();

    return 0;
}

MyClass.cpp

void init()
{
    MyQtQuickClass view;

    QThread* GUIthread = new QThread(this);

    view.moveToThread(GUIthread);
    QObject::connect(GUIthread, SIGNAL(started()), &view, SLOT(init()));

    GUIthread.start();
}

MyQtQuickCLass.cpp

void init()
{
    QQmlContext* rootContext = this->rootContext();

    // Setup view code here

    this->show();

    QGuiApplication::instance()->exec();
}

像这样我得到这个错误: QQmlEngine:非法尝试连接到与 QML 引擎 QQmlEngine(0xdf6e70) 不同的线程中的 QQmlContext(0x120fc60)。

有解决办法吗?或者直接在第二个线程中创建QML引擎的方法?

QObject 与父 QObject 的线程或当前线程(如果它们没有父线程)具有线程关联。在您的示例中,很可能在 MyQtQuickClass 的实例化期间创建的一些 QObject 与创建它们的线程具有亲和力。在 GUIthread 中创建 MyQtQuickClass 可以解决这个问题。

但是,所有Qt windows 必须 运行与QGuiApplication在同一个线程中,如果您尝试,您的应用程序很可能会崩溃。

如果您希望 QQuickView 位于 main() 线程之外,那么您必须:

  1. 创建一个新的 std::thread(不是 QThread,因为它是 QObject,所以不能在您的 QGuiApplication 之前创建)
  2. 运行 该线程中的一个 init() 函数。让它实例化您的 QGuiApplication 并启动事件循环。
  3. 也在该线程中创建您的 QQuickView
  4. 确保仅从该线程访问所有 GUI 对象。
  5. 确保您的 main() 线程在您的 QGuiApplication 在您的其他线程中创建之前不会创建任何 QObject

有关详细信息,请参阅 How to avoid Qt app.exec() blocking main thread