[SOLVED] Creating a Component Dynamically from C++, accesing other items by id??



  • i have some qml code like
    @
    Item{
    id:laneContainer
    Component.onCompleted: {
    Script.laneContainer = laneContainer;
    var laneComp = Qt.createComponent("Lane.qml");
    Script.laneComp = laneComp;
    }
    @

    and from the Script i can run " laneComp.createObject(laneContainer) " and an istance of Lane{} is created!

    but if i try to do something like this with c++ i CANNOT!
    i have a class (which i passed in the declarativeview using setContextProperty) with the members:
    QDeclarativeComponent *m_laneComp;
    QDeclarativeItem *m_laneContainer;

    and some setters functions to pass the qml address of the objects, everything is ok so far.
    but compiler shows an error if i try to write
    " m_laneComp.createObject(m_laneContainer);"

    the error is: QDeclarativeComponent::createObject(QObject*)' is protected

    what is wrong???

    Thanks in advance!
    This is my first post, i just registered in the forum. In the past month i've been spending a ton of time learning Qt. Having lots of fun!! :D



  • Hi,

    The createObject() function is meant to be used from QML, and not from C++. From C++, you can use the create() function and then set the parent via setParentItem().

    Regards,
    Michael



  • Thanks! But now i have another problem

    In the Lane.qml which i am creating dynamically, i had binded values from other qml components which are in my main.qml

    imagine:

    @
    Item{
    id: container
    property int myValue: ...
    .....
    Rectangle{
    id: myRectangle
    ....

    Item{
    id:laneContainer
    Component.onCompleted: {
    var laneComp = Qt.createComponent("Lane.qml");
    myClass.setLaneComp(laneComp);
    myClass.setLaneContainer(laneContainer);
    }

    }
    @

    and in the Lane.qml i have
    width: container.myValue for example

    and with c++ i run:
    @
    m_laneQml = m_laneComp.create();
    m_laneQml.setParent(m_laneContainer);
    @

    the compiler shows an error "ReferenceError: Can't find variable: container"

    (when i was using javascript, this worked like charm, but i want to do it from c++ cause the "Lane.qml" is just the "gui" for a class, and i want to do the management from c++)

    i tried to pass the Qdeclarativeview's rootcontext when creating( m_laneComp.create(m_rootContext); but still...)

    Is there a solution, will i be able to do this?? Or should i stick with javascript and find ways to communicate with my classes? (though this is a pain in the ass..)
    Thanks!



  • Please some help in this “ReferenceError: Can’t find variable: container” error.

    I'm at a dead end because of this error...

    and generally this error appears even if i have something like:

    width: parent.width

    inside an object which i create dynamically (notice that this happens only when created from c++, when created from javascript everything works like charm)



  • [quote author="inspired" date="1341568806"]
    i tried to pass the Qdeclarativeview's rootcontext when creating( m_laneComp.create(m_rootContext); but still...)
    [/quote]

    You are on the right track! It sounds like the root context isn't the correct context in this case. Try calling QDeclarativeEngine::contextForObject() on the root object of the view (or on m_laneContainer), and using that context in create() instead.

    [quote author="inspired" date="1341568806"]
    Is there a solution, will i be able to do this?? Or should i stick with javascript and find ways to communicate with my classes? (though this is a pain in the ass..)
    [/quote]

    What sort of communication between the layers are you after? What are you finding doesn't work well?

    Regards,
    Michael



  • [quote author="inspired" date="1341670690"]
    and generally this error appears even if i have something like:
    width: parent.width
    [/quote]

    Switching from a sequence of:

    create()

    setParent()/setParentItem()

    to a sequence of:

    beginCreate()

    setParent()/setParentItem()

    completeCreate()

    should fix these types of errors (which are transient errors that exist because with the first sequence the bindings are run before parent is set)

    Regards,
    Michael



  • [quote author="mbrasser" date="1341792247"][quote author="inspired" date="1341568806"]
    i tried to pass the Qdeclarativeview's rootcontext when creating( m_laneComp.create(m_rootContext); but still...)
    [/quote]

    You are on the right track! It sounds like the root context isn't the correct context in this case. Try calling QDeclarativeEngine::contextForObject() on the root object of the view (or on m_laneContainer), and using that context in create() instead.

    [quote author="inspired" date="1341568806"]
    Is there a solution, will i be able to do this?? Or should i stick with javascript and find ways to communicate with my classes? (though this is a pain in the ass..)
    [/quote]

    What sort of communication between the layers are you after? What are you finding doesn't work well?

    Regards,
    Michael
    [/quote]

    wow, i tried m_view->engine()->contextForObject(m_container) and now from my created objects i can access other objects just fine! :D

    The problem i had was that i had various variables which i was using in the varius qml files with binding (eg i had a zoomFactor variable which when changed it changed numerous items dimensions), and i had them all as properties in a qml file.
    Though i solved this using a more elegant way, making a Qobject and having my values as Q_PROPERTY, so binding worked just fine, and in a much more cleaner and obvious way.
    Learning Qt is fun! :D
    (anyone else reading this, see https://idlebox.net/2010/apidocs/qt-everywhere-opensource-4.7.0.zip/qtbinding.html )

    Also the sequence of

    @
    beginCreate()
    setParent()/setParentItem()
    completeCreate()
    @
    worked just fine!
    Thanks a lot Michael!! :)



  • Is there any way you can post a code snippet of how you solved this? I'm having the same problem but can't seem to get it working using your methods. I've changed to the sequence using beginCreate() and still have the same problem.

    Thanks.



  • [quote author="fatdollar" date="1379611054"]Is there any way you can post a code snippet of how you solved this? I'm having the same problem but can't seem to get it working using your methods. I've changed to the sequence using beginCreate() and still have the same problem.

    Thanks.[/quote]
    This is now an old abandoned project, so i don't remember anything about how/what etc...
    i'm just posting this in case it helps

    @
    Lane::Lane(QObject *parent, QDeclarativeView *view, QDeclarativeItem laneQml) :
    QObject(parent)
    {
    m_name = "lane class";
    m_laneQml = laneQml;
    m_view = view;
    m_arrangeContainer = m_laneQml->findChild<QDeclarativeItem
    >("arrangeContainer");
    m_itemComp = new QDeclarativeComponent(m_view->engine(), QUrl::fromLocalFile("qml/Tcp_grid/Item.qml"), this);
    m_name = "New track";
    }

    void Lane::addItem(double start, double length, QString source)
    {
    QDeclarativeContext *context = new QDeclarativeContext(m_view->engine()->contextForObject(m_view->rootObject()));
    Item *item = new Item(this, qobject_cast<QDeclarativeItem *>(m_itemComp->beginCreate(context)), m_arrangeContainer, m_view);
    item->setStart(start);
    item->setLength(length);
    item->setSource(source);
    context->setContextProperty("itemClass", item);
    context->setParent(item);
    m_itemComp->completeCreate();
    m_itemList.append(item);
    }
    @
    and about the Item

    @Item::Item(QObject *parent, QDeclarativeItem *item, QDeclarativeItem *arrange, QDeclarativeView *view) :
    QObject(parent)@



  • Hey thanks a lot that helped me out. However it also confirmed my fear that I would need access to the view from main to do what i'm wanting. :(


Log in to reply
 

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