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. How to set the parent item of a QDeclarativeComponent prior creation

How to set the parent item of a QDeclarativeComponent prior creation

Scheduled Pinned Locked Moved QML and Qt Quick
5 Posts 2 Posters 5.3k 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.
  • A Offline
    A Offline
    agroyer
    wrote on last edited by
    #1

    I am trying to move the creation of qml pages from QML to C++:

    First, I create the parent page
    @
    mView = new QDeclarativeView();
    mView->setSource(QUrl("qrc:/libpages/parentPage.qml"));
    mView->show();
    @

    then I create the other pages with QDeclarativeComponent.:
    @
    QDeclarativeComponent *component = new QDeclarativeComponent(mView->engine(), mView->rootObject());
    component->loadUrl(QUrl("qrc:/libpages/myPage.qml"));
    ...
    @

    I want to inherit the context of the parentPage, so I use QDeclarativeEngine::contextForObject(mView->rootObject()).
    I want also to define the parent item of myPage.qml to be parentPage.qml.
    @
    QObject * object = component->beginCreate(QDeclarativeEngine::contextForObject(mView->rootObject()));
    if (NULL == object)
    {
    component->completeCreate();
    }
    else
    {
    object->setProperty("parent", QVariant::fromValue(qobject_cast<QDeclarativeItem*>(mView->rootObject())));
    object->setProperty("visible", QVariant(false));
    component->completeCreate();
    }
    @

    First question: is the above code correct ?
    Second question: is there an easier way to set the parent element of myPage.qml, prior to the beginCreate() call? The qml code "object Component::createObject ( Item parent, object properties )" accepts a parent element. Is there an equivalent in c++ ?

    Thanks
    Anthony

    1 Reply Last reply
    0
    • A Offline
      A Offline
      agroyer
      wrote on last edited by
      #2

      I found today that this way of initializing the object make my application crash.
      This is caused by a DeferredDelete event because my object had no parent.

      I understood that I need also to call "QObject::setParent(QObject*)".
      Initializing the "parent" property of the QDeclarativeItem is necessary to place the item in the scene but it is not enough. This is 2 different things.

      The new code is
      @
      QObject * object = component->beginCreate(QDeclarativeEngine::contextForObject(mView->rootObject()));
      if (NULL == object)
      {
      component->completeCreate();
      }
      else
      {
      object->setProperty("parent", QVariant::fromValue(qobject_cast<QDeclarativeItem*>(mView->rootObject())));
      object->setParent(mView->rootObject());
      object->setProperty("visible", QVariant(false));
      component->completeCreate();
      }
      @

      Is there a way to achieve the init of both "parents" within one call ?

      1 Reply Last reply
      0
      • C Offline
        C Offline
        chriadam
        wrote on last edited by
        #3

        Out of interest, why are you using beginCreate() instead of create()?
        Note that in QML you can pass a parent as a parameter (ie, component.createObject(parentArg)).
        In C++ you can set the ownership explicitly to be CppOwnership which will prevent the engine from cleaning up the item due to (implied) JS ownership.

        Using object->setProperty("parent", ...) is generally wrong. If you have a QObject and you want to set its (ownership) parent, use QObject::setParent().

        1 Reply Last reply
        0
        • A Offline
          A Offline
          agroyer
          wrote on last edited by
          #4

          [quote author="chriadam" date="1334877825"]Out of interest, why are you using beginCreate() instead of create()?
          [/quote]
          My code uses "Component.onCompleted" to execute some javascript code that will use the parent.width. In case I call create(), "Component.onCompleted" will be executed with a "parent" property set to "null". If I set later on the "parent" property, the "Component.onCompleted" javascript code will not be executed again. So I must set explicitly a "onParentChanged" handler to call again the init code. This causes a new execution of the javascript code plus property bindings for the "parent" property, thus creating a longer creation time.

          As explained in http://qt-project.org/doc/qt-4.8/qdeclarativecomponent.html#beginCreate, beginCreate and completeCreate allows me to distinguish the init steps and I can insert between boths the init of the parent item.
          [quote]
          Note that in QML you can pass a parent as a parameter (ie, component.createObject(parentArg)).
          [/quote]
          From my point of view, component.createObject(parentArg) will set the "parent" property of the QDeclarativeItem plus maybe the QObject::setParent(QObject*).
          [quote]
          In C++ you can set the ownership explicitly to be CppOwnership which will prevent the engine from cleaning up the item due to (implied) JS ownership.
          [/quote]
          I understand better. If I want to avoid my object being destroyed, I can replace
          @
          object->setParent(mView->rootObject());
          @

          with
          @
          QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::CppOwnership);
          @

          Thanks
          [quote]

          Using object->setProperty("parent", ...) is generally wrong. If you have a QObject and you want to set its (ownership) parent, use QObject::setParent().
          [/quote]

          I have not confused object->setProperty("parent", ...) and QObject::setParent().
          In fact, the call
          @
          object->setProperty("parent", QVariant::fromValue(qobject_cast<QDeclarativeItem*>(mView->rootObject())));
          @
          is equivalent to
          @
          qobject_cast<QDeclarativeItem*>(object)->setParentItem(qobject_cast<QDeclarativeItem*>(mView->rootObject()));
          @
          This call is necessary so that the QML item has a parent item and can be displayed.

          So, my initial question came again, is there a way to simplify the following code with keeping in mind that "Component.onCompleted" must be executed with a correct parent item set (like createObject in javascript ?).
          @
          QObject * object = component->beginCreate(QDeclarativeEngine::contextForObject(mView->rootObject()));
          if (NULL == object)
          {
          component->completeCreate();
          }
          else
          {
          object->setProperty("parent", QVariant::fromValue(qobject_cast<QDeclarativeItem*>(mView->rootObject())));
          object->setParent(mView->rootObject()); //OR QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::CppOwnership);
          object->setProperty("visible", QVariant(false));
          component->completeCreate();
          }
          @

          1 Reply Last reply
          0
          • C Offline
            C Offline
            chriadam
            wrote on last edited by
            #5

            Yikes, ok, that setParentItem / "parent" property name thing is interesting - I didn't know that ;-) Thanks.
            The fact that the parent isn't set prior to the onCompleted callback being called sounds like a bug, to me.
            /edit: well, the fact that we don't have API to allow a parent argument, perhaps would be a better way of putting it. What you do currently, seems ok to me too, as the beginCreate()/completeCreate() split exists to allow the finer control which you use.

            Regarding ownership, setting a parent object will prevent the object from being collected, but won't (necessarily) prevent the parent object from being collected (unless it explicitly has CppOwnership). In your case, I believe that it will have explicit CppOwnership anyway, since it is the root object of the view. Thus, I think my advice about explicitly setting the ownership semantics of the child object was unnecessary. Sorry for the confusion!

            I'll look into the "parent not set until after the onCompleted handler being called" issue and then respond to this thread again.

            Cheers,
            Chris.

            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