--- title: 7. Parents and parent items layout: docs --- :doctitle: 7. Parents and parent items :notitle: == Parents and parent items Creating an app with QSkinny consists of creating controls, putting them into layouts and nesting layouts and controls inside each other. The nesting already creates some sort of a hierarchy in the app, see the "Nesting layouts" section in the link:Layouts.html[layouts page]. In more general terms, all controls are part of several hierarchies: * The *object tree*. This is a tree of `QObject` instances which manages lifetime: Objects created with a parent will get deleted whenever their parent is deleted. For more information, see the Qt documentation on https://doc.qt.io/qt-5/objecttrees.html[Object Trees & Ownership]. * The *item tree*. This is a tree of items displayed on the screen, i.e. `QQuickItem` instances. Qt will traverse the item tree when rendering items on the screen. The positioning of an item depends on its parent item, e.g. layouts will position their child items according to certain policies. In addition, visual items will inherit properties from its parent item like visibility or opacity. The item tree is often similar to the object tree, but not necessarily: Instances of `QQuickItem` can have a parent item set, but have another parent, or no parent at all. See also the Qt documentation on https://doc.qt.io/qt-5/qtquick-visualcanvas-visualparent.html[Concepts - Visual Parent in Qt Quick]. * The *scene graph*. The scene graph contains a representation of graphic primitives like rectangles, textures (i.e. images) and text, to allow efficient rendering on the screen with OpenGL or other backends. This is described in more details in link:scene-graph.html[scene graph representations of controls]. === Example Let’s look at the "Nesting layouts" example from the link:Layouts.html[layouts documentation]. The UI looks like this: .UI with nested layouts image::/doc/tutorials/images/nesting-layouts.png[Nested layouts] The code for this UI is below: [source] .... auto* outerBox = new QskLinearBox( Qt::Vertical ); auto* topBar = new QskLinearBox( Qt::Horizontal, outerBox ); auto* topLabel1 = new QskTextLabel( "top bar label 1", topBar ); auto* topLabel2 = new QskTextLabel( "top bar label 2", topBar ); auto* topLabel3 = new QskTextLabel( "top bar label 3", topBar ); auto* mainBox = new QskLinearBox( Qt::Horizontal, outerBox ); auto* menuBox = new QskLinearBox( Qt::Vertical, mainBox ); auto* menuLabel1 = new QskTextLabel( "menu 1", menuBox ); auto* menuLabel2 = new QskTextLabel( "menu 2", menuBox ); auto* menuLabel3 = new QskTextLabel( "menu 3", menuBox ); auto* mainText = new QskTextLabel( "here main area", mainBox ); QskWindow window; window.addItem( outerBox ); window.show(); .... ==== Object tree In the example above, when we created a new element, we always passed the `QObject` parent as an argument to the constructor, which is good practice. We do that for instance in this line: [source] .... auto* topLabel1 = new QskTextLabel( "top bar label 1", topBar ); .... This makes sure `topBar` is a parent of `topLabel1`. It means that when `topBar` is deleted, it will automatically delete `topLabel1`, because the latter is a child of the `topBar`. Below is an image of the object tree, i.e. the `QObject` parent-child relationship. The `QskWindow` is hereby the parent of the `QQuickRootItem`, which itself is the parent of the `outer box`, and so on. For information on how to obtain this tree, see https://doc.qt.io/qt-5/qobject.html#dumpObjectTree[QObject::dumpObjectTree()]. .QObject tree (and item tree) of the nested layouts UI image::/doc/tutorials/images/object-hierarchy.png[QObject hierarchy] ==== Item tree The Item tree for the example above is identical to the object tree. As described, we always pass the parent object in the constructor: [source] .... auto* topLabel1 = new QskTextLabel( "top bar label 1", topBar ); .... The line above will (in addition to the setting the parent) also ensure that `topBar` will be a *parent item* of `topLabel1`; this is done by the `QQuickItem` constructor. Even if we had not passed the parent in the constructor, we could still add the label to the `topBar` via an explicit call: [source] .... auto* topLabel1 = new QskTextLabel( "top bar label 1" ); topBar->addItem( topLabel1 ); .... The call to `addItem()` above sets the parent item of `topLabel1` to `topBar` and thus the latter will display it as one of its children. In this case it would also set the parent, because the `topLabel1` does not have one yet. In other words, setting a parent item will also set the parent *if* the parent is null. So since the `topBar` is a parent item of `topLabel1`, it means that `topLabel1` will inherit settings like visibility and opacity from `topBar`. For instance, if we set the the visibility of the `topBar` to false, all its child items will be invisible as well (which in this case would be all top bar labels). If we set the opacity to 0.2, all its child items will be almost transparent: [source] .... topBar->setOpacity( 0.2 ); .... .Changing opacity of an item will affect all its child items image::/doc/tutorials/images/nesting-layouts-item-tree-1.png[Changing the item tree] ==== Difference in object trees and item trees As an example for when the object tree and item tree differ, let’s decide to add a bottom bar to our UI and move our `topLabel1` from the top bar to the bottom bar. This is easy: [source] .... auto* bottomBar = new QskLinearBox( Qt::Horizontal, outerBox ); topLabel1->setParentItem( bottomBar ); .... .Moving a label from the top bar to the bottom bar image::/doc/tutorials/images/nesting-layouts-item-tree-2.png[Moving a label to the bottom bar] Now we decide to get rid of our top bar altogether: [source] .... topBar->deleteLater(); .... This will also delete our label from the bottom bar: .Deleting the top bar will delete all its children image::/doc/tutorials/images/nesting-layouts-item-tree-3.png[Deleting the top bar] The reason why the label from the bottom bar was also deleted is that with the call to `setParentItem()` above we set a new parent item; the parent, however, was still `topBar` (the call to `setParentItem()` did not change the parent, because it was not null). So when the `topBar` was deleted, it deleted all of its children, including the moved label `topLabel1`. After we moved the label to the bottom bar, the object tree was different from the item tree, hence we got a surprising result when deleting the top bar. It is a good idea to try to keep the trees the same, and be aware of the existence of both of them. If we reparent our label to the bottom bar before deleting the top bar, we get the desired effect: [source] .... topLabel1->setParent( bottomBar ); topLabel1->setParentItem( bottomBar ); topBar->deleteLater(); .... .Reparenting the label will keep it alive when deleting the top bar image::/doc/tutorials/images/nesting-layouts-item-tree-4.png[Reparenting the item]