3

The following little QML application blocks forever when run (Qt 5.14.2, Windows 10). My idea was to create a generic App containing the business logic and have an QtUI on top of it. The blocking does not happen when I remove the Scene3D in the QML, so I think the issue is somehow related to Qt3D. I'm stuck, what am I doing wrong?

main.cpp:

#include "QtUI.h"

int main(int argc, char** argv) {
    App app;
    QtUI gui(app, argc, argv);
    app.setUI(&gui);
    app.init();
    QtUI::exec();
}

App.h:

#ifndef APP_H
#define APP_H

class App {
public:
    class UI {
    public:
        virtual void onFirst() = 0;
        virtual void onSecond() = 0;
    };
    void setUI(UI* ui);
    void init();

private:
    UI* ui_ = nullptr;
};

#endif

App.cpp:

#include "App.h"

void App::init() {
    ui_->onFirst();
    ui_->onSecond();
}


void App::setUI(App::UI* ui) {
    ui_ = ui;
}

QtUI.h:

#ifndef QTUI_H
#define QTUI_H

#include <QApplication>
#include <QQmlApplicationEngine>
#include "App.h"

class QtUI : public QGuiApplication, public App::UI {
Q_OBJECT
public:
    explicit QtUI(App& app, int& argc, char** argv);
    void onFirst() override;
    void onSecond() override;

signals:
    void first();
    void second();

private:
    App& app_;
    QQmlApplicationEngine engine_;
};

#endif

QtUI.cpp

#include "QtUI.h"
#include <QQmlContext>

QtUI::QtUI(App& app, int& argc, char** argv)
        : QGuiApplication(argc, argv),
          app_(app) {
    engine_.rootContext()->setContextProperty("app", this);
    engine_.load("qrc:/Main.qml");
}

void QtUI::onFirst() {
    emit first();
}

void QtUI::onSecond() {
    emit second();
}

Main.qml

import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Window 2.14
import QtQuick.Scene3D 2.14
import Qt3D.Core 2.14
import Qt3D.Render 2.14
import Qt3D.Input 2.14
import Qt3D.Extras 2.14

ApplicationWindow {
    visible: true

    StackView {
        id: stack
        anchors.fill: parent
    }

    Connections {
        target: app
        onFirst:   stack.push(first);
        onSecond:  stack.push(second);
    }

    Component {
        id: first
        Item {
            Scene3D {
                Entity {
                    components: [
                        RenderSettings {
                            activeFrameGraph: ForwardRenderer {
                                clearColor: "red"
                            }
                        }
                    ]
                }
            }
        }
    }

    Component {
        id: second
        Item {
            Button{ text: "Foo"}
        }
    }
}
marsl
  • 959
  • 1
  • 14
  • 25
  • I'm concerned that you are sending the onFirst and onSecond signals into the QML engine before it has had a chance to finish initializing. I'd try firing the push() calls from a Component.onCompleted hander so you know the QML runtime is ready for them. – David K. Hess Apr 28 '20 at 01:48
  • Thanks for your hint @DavidK.Hess, but it seems to be more complicated than that. I filed a bug report in Qt: https://bugreports.qt.io/browse/QTBUG-83871 – marsl Apr 29 '20 at 10:18
  • You need to install Qt debug info and sources (or build a debug build of qt yourself), then break the blocked application in the debugger and see where exactly it blocks. That may give you hints as to workarounds. Qt comes with full source code so such issues are much easier to diagnose than they otherwise would be. I highly recommend using a developer build of Qt. – Kuba hasn't forgotten Monica Apr 30 '20 at 03:40

1 Answers1

1

I've used replace method of a StackView as a workaround.

c4pQ
  • 884
  • 8
  • 28