Access to an After Loaded View From Qml To C++

  • Hello ! I'm new in Qt Devlopment and I have a short question that certainly won't take long time to resolve for such specialists ;)

    I made a Loader to display a splashscreen that will load the main.qml thereafter like this:

    QDeclarativeView view;

    I would like to connect some stuff to a child of my PageStackWindows in main.qml : mainMenu.qml

    The problem if I do that :

    @ QObject rootObject = dynamic_cast<QObject>(view.rootObject());
    QObject mainMenu = rootObject->findChild<QObject>("mainMenu");
    QObject::connect(&myClass, SIGNAL(data(QVariant)), mainMenu, SLOT(updateData(QVariant)));@

    I get this error: QObject::connect: Cannot connect <MyClass>::data(QVariant) to (null)::updateData(QVariant)

    Yes mainMenu is null. Of course I put: objectName: "mainMenu"

    In my MainAppLoader.qml I have this that load the main.qml :

    @Loader {
    id: mainLoader
    width: parent.width
    height: parent.height

        Timer {
            id: firstPhaseTimer
            interval: 700
            running: true
            repeat: false
            onTriggered: {
                if (!mainLoader.Loading) {
                    // Start to load the main application
                    mainLoader.source = Qt.resolvedUrl("main.qml");

    Do you know how I could get / use the reference of my main.qml / MainMenu.qml freshly created to connect what I want from cpp ?

    If I do the same without my splashScreenLoader, it works.

    Thanks !

  • Moderators

    You are probably asking for connection too early. Either emit a signal to C++ once loading is ready, or make the connection in QML.

  • You say it's possible to connect a freshly created QML View with CPP in QML ?

    In other words, I just need to warn Cpp with a signal when my main.qml is created mainLoader.source = Qt.resolvedUrl("main.qml");
    to tell him to make the rootObject->findChild<QObject*>("mainMenu"); and connect it ? that's all ?

    I'l try tomorow, thank you for the quick anwser !

  • Moderators

    I think so. To be honest I did not take time to read through and fully understand your post, I just gave a first impression.

    The definite point is that object needs to be ready before meta objects can be connected.

    BTW. you don't need the dynamic_cast line, root object should have ::findChild() available.

  • As I see it, you have the following options:

    1.) Call a C++ slot after the Loader finished, as sierdzio suggested
    You can call a C++ function from QML by registering the C++ object as a context property with @QDeclarativeContext::setContextProperty()@ and then call the slot function of this object. This is useful if the object you are calling only exists once, i.e. a Singleton.

    2.) By registering the C++ item as a QML item. You can do that with @qmlRegisterType<CppClassName>("NamespaceForImport", 1, 0 "QMLItemName")@

    In that way, you could also directly access the signal from QML, e.g. if the signal is called @dataChanged(QVariant newData)@

    , you can access it in QML with
    import NamespaceForImport 1.0

    QMLItemName {
    onDataChanged: { ... "newData" is available as parameter ... }

  • Hello again, I think I'm doing it wrong

    I made a call to my C++ object when QML completed the launched of MainMenu.qml like this:

    in main.cpp:

    @QDeclarativeView view;

    in MainMenu.qml

    @Component.onCompleted: {

    in MyClass c++

    @void MyClass::mainMenuCreated()
    qDebug() << "Hello I'm created";


    This is working but now, How can I have access to QDeclarativeView / QDeclarativeContext from MyClass to connect my freshly created qml file with c++ signal ? I only have access in main.cpp and tried to pass it in MyClass constructor, but it seems private. I think I'm doing something wrong :D

  • You should be able to pass it with the constructor - what do you mean that it is private? You have control over MyClass implementation, so you can just do something like the following:
    //in main.cpp:
    QMLApplicationViewer viewer;

    MyClass myClass = new MyClass(viewer);

    //and in MyClass constructor you can access the QDeclarativeEngine from the QMLApplicationViewer with:

    MyClass::MyClass(QMLApplicationViewer &viewer) {
    QDeclarativeEngine *engine = viewer.engine();
    QDeclarativeContext *context = engine->rootContext;

    From the QDeclarativeView you can call the method rootContext() to get the context in your MyClass.

    Alternatively, to receive the context from a QDeclarativeItem which you instantiate from QML, you can use the following:
    @QDeclarativeContext *currentContext = QDeclarativeEngine::contextForObject(this);
    QDeclarativeEngine *declarativeEngine = currentContext->engine();
    QDeclarativeContext *rootContext = declarativeEngine->rootContext();@

  • I surely made a mistake somewhere :(

    In main.cpp

    @QDeclarativeView view;
    MyClass *myClass = new MyClass(view);


    @class MyClass : public QObject
    explicit MyClass();
    explicit MyClass(QDeclarativeView &view);


    public slots:

    QDeclarativeView mQDeclarativeView;



    @MyClass::MyClass() {

    MyClass::MyClass(QDeclarativeView &view) {
    mQDeclarativeView = view;

    Got this error:

    @ error : 'QDeclarativeView& QDeclarativeView::operator=(const QDeclarativeView&)' is private

  • Moderators

    Use a pointer. You are trying to use an assignment operator while all QObject children cannot be copied.

  • It was what I did first but you gave me an example with references :P

    It's working now :)

    The final code for visitors:

    @void MyClass::mainMenuCreated()
    qDebug() << "Hello I'm created";

    QObject *menu = (mQDeclarativeView->rootObject())->findChild<QObject*>("mainMenu");
    QObject::connect(this, SIGNAL(data(QVariant)), menu, SLOT(updateData(QVariant)));


    And now my function from MainMenu.qml is called :)

    @updateData(text) { console.log("I'm here"); }

    If you see any improvment that could be made or other better technique, don't hesitate :)

    Thank you so much for this lesson :P

  • No worries :)

    As a tiny improvement, it's good practice to name context properties with a small first letter to be able to distinguish them from classes/QML components. So instead of "MyClass", name it "myClass" - you could access enums for instance from QML with "MyClass.enumName" then, and so don't mix it up with a context property access.

    Also, the data-signal could be renamed to dataChanged, as it is probably reflects more what it does. But that's syntactic sugar, just a suggestion..

Log in to reply