QML Context lost when QML component is created from C++



  • Hello,

    I have a simple C++ QQuickItem component that instantiates a QQmlComponent.
    But within the instantiated QQmlComponent, the ids of other QML components are not known anymore (see detailed example below)
    Apparently, the context is lost.

    The resulting log shows

    qrc:/main.qml:35: ReferenceError: textId is not defined
    qml: Text(not delegate)=Hello World
    

    Is this something I can fix? Or is this 'logical'/'explainable' somehow?

    The example code below illustrates the problem and consists of

    • main.cpp
    • MyQuickComponent.h
    • MyQuickComponent.cpp
    • main.qml

    Thanks in advance,

    Marc
    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include "myquickcomponent.h"
    
    QQmlApplicationEngine *engine;
    
    int main(int argc, char *argv[])
    {
        qmlRegisterType<MyQuickComponent>("Mine", 1, 0, "MyQuickComponent");
        QGuiApplication app(argc, argv);
    
        engine = new QQmlApplicationEngine();
        engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    

    MyQuickComponent.h

    #ifndef MYQUICKCOMPONENT_H
    #define MYQUICKCOMPONENT_H
    #include <QQuickPaintedItem>
    #include <QPainter>
    
    class MyQuickComponent : public QQuickPaintedItem
    {
    Q_OBJECT
        Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
    
    public:
        MyQuickComponent(QQuickItem *parent = 0);
        void paint(QPainter *painter);
    
        QQmlComponent *delegate() const { return m_delegate; }
        void setDelegate(QQmlComponent *delegate);
    
    
    Q_SIGNALS:
        void delegateChanged();
    
    private:
        QQmlComponent *m_delegate;
    
    };
    
    #endif // MYQUICKCOMPONENT_H
    

    MyQuickComponent.cpp

    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "myquickcomponent.h"
    
    MyQuickComponent::MyQuickComponent(QQuickItem *parent)
    : QQuickPaintedItem(parent), m_delegate(NULL)
    {
    }
    
    void MyQuickComponent::paint(QPainter *painter)
    {
    }
    
    extern QQmlApplicationEngine *engine;
    void MyQuickComponent::setDelegate(QQmlComponent *delegate)
    {
        if (delegate != m_delegate) {
            m_delegate = delegate;
            emit delegateChanged();
        }
    
        //create object
        QQmlContext *context = new QQmlContext(engine->rootContext());
        context->setContextObject(this);
        QQuickItem *object = qobject_cast<QQuickItem*>(m_delegate->create(context));
        //QQuickItem *object = qobject_cast<QQuickItem*>(m_delegate->beginCreate(engine->rootContext()));
        QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
        object->setParentItem(this);
        object->setParent(this);
        object->setProperty("color", "red");
        object->setProperty("y", 200);
        //m_delegate->completeCreate();
    
    }
    

    And finally main.qml

    import QtQuick 2.5
    import QtQuick.Window 2.2
    
    import Mine 1.0
    
    Window {
        visible: true
        width:600
        height: 600
    
        Text {
            id: textId
            text: qsTr("Hello World")
            anchors.centerIn: parent
        }
    
        Rectangle {
            width:100
            height:100
            id: notdelegate
            //here I can access textId
            Component.onCompleted: console.log("Text(not delegate)="+textId.text)
            color: 'green'
        }
    
        //MyQuickComponent is a C++ QQuickItem that creates the delegate component
        MyQuickComponent {
            width:parent.width
            height: parent.width
            delegate: Rectangle {
                width:100
                height:100
                id: delegate
                //here I can't access textId !!
                Component.onCompleted: console.log("Text(delegate)="+textId.text)
                color: 'green'
            }
        }
    }


  • Context actually exist and is not lost. Issue is getting from m_delegate.create(...) call. I don't know why. May be it failed to access the textId due some bug. I verified all the contexts, objects etc. Everything looks fine.



  • Apparently, it was sufficient to replace the line below in MyQuickComponent.cpp

    QQmlContext *context = new QQmlContext(engine->rootContext());
    

    with

    QQmlContext *context = m_delegate->creationContext();
    

    Note: how can I mark this question as fixed/solved?


  • Moderators

    @MarcVanDaele Thanks for sharing the solution.

    how can I mark this question as fixed/solved?

    Under Topic Tools combobox there's an option as "Mark as Solved". I have marked it now.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.