Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. [SOLVED] Creating a Component Dynamically from C++, accesing other items by id??
QtWS25 Last Chance

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

Scheduled Pinned Locked Moved QML and Qt Quick
10 Posts 3 Posters 3.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    inspired
    wrote on last edited by
    #1

    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

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mbrasser
      wrote on last edited by
      #2

      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

      1 Reply Last reply
      0
      • I Offline
        I Offline
        inspired
        wrote on last edited by
        #3

        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!

        1 Reply Last reply
        0
        • I Offline
          I Offline
          inspired
          wrote on last edited by
          #4

          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)

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mbrasser
            wrote on last edited by
            #5

            [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

            1 Reply Last reply
            0
            • M Offline
              M Offline
              mbrasser
              wrote on last edited by
              #6

              [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

              1 Reply Last reply
              0
              • I Offline
                I Offline
                inspired
                wrote on last edited by
                #7

                [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!! :)

                1 Reply Last reply
                0
                • F Offline
                  F Offline
                  fatdollar
                  wrote on last edited by
                  #8

                  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.

                  1 Reply Last reply
                  0
                  • I Offline
                    I Offline
                    inspired
                    wrote on last edited by
                    #9

                    [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)@

                    1 Reply Last reply
                    0
                    • F Offline
                      F Offline
                      fatdollar
                      wrote on last edited by
                      #10

                      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. :(

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved