1

Goal

I need to know when and how the collective geometry of the children of Foo, a subclass of QQuickItem, changes.

Problem

I have connected a lambda to the QQuickItem::childrenRectChanged signal, but it is never emitted. Strangely enough, if I call childrenRect somewhere, the signal starts getting emitted. childrenRect is a getter method, not a setter, so I see no reason for this "fix".

Question

Why a seemingly unrelevant call "fixes" the emition of the signal and how to make this work as expected without calling childrenRect?

Reproducible example

Here is an example I have prepared to demonstrate the issue:

Foo.h

#include <QQuickItem>

class Foo : public QQuickItem
{
    Q_OBJECT
public:
    explicit Foo(QQuickItem *parent = nullptr) :
        QQuickItem(parent) {
        childrenRect(); // After commenting this childrenRectChanged is not emitted anymore
        connect(this, &Foo::childrenRectChanged, [this](){
            qDebug() << childrenRect();
        });
    }
};

The class is registered in main.cpp like this:

qmlRegisterType<Foo>("Foo", 1, 0, "Foo");

and used in main.qml in the following way:

import QtQuick 2.15
import QtQuick.Window 2.15
import Foo 1.0

Window {
    width: 300; height: 400; visible: true; color: "black"
    title: qsTr("Children Rect")

    Foo {
        anchors.centerIn: parent

        Rectangle {
            anchors.bottom: lightMid.top
            anchors.horizontalCenter: parent.horizontalCenter
            width: 50; height: width; radius: 0.5*width
            color: "red"
        }

        Rectangle {
            id: lightMid

            anchors.centerIn: parent
            width: 50; height: width; radius: 0.5*width
            color: "yellow"
        }

        Rectangle {
            anchors.top: lightMid.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            width: 50; height: width; radius: 0.5*width
            color: "green"
        }
    }
}

Edit

The documentation of QQuickItem::childrenRect says:

This property holds the collective position and size of the item's children.

This property is useful if you need to access the collective geometry of an item's children in order to correctly size the item.

Access functions:

QRectF childrenRect()

However, as @Amfasis mentioned in the comments, this method is not just a simple getter. Here is the code:

QRectF QQuickItem::childrenRect()
{
    Q_D(QQuickItem);
    if (!d->extra.isAllocated() || !d->extra->contents) {
        d->extra.value().contents = new QQuickContents(this);
        if (d->componentComplete)
            d->extra->contents->complete();
    }
    return d->extra->contents->rectF();
}
scopchanov
  • 7,966
  • 10
  • 40
  • 68
  • 1
    As you can see from [woboq](https://code.woboq.org/qt5/qtdeclarative/src/quick/items/qquickitem.cpp.html#_ZN10QQuickItem12childrenRectEv) it is not a simple getter, but I'm unsure how this affects your situation – Amfasis Oct 15 '20 at 05:37
  • Can you explain why you need to know the geometry? The example that you give can probably rewritten with a ColumnLayout, but how far from your real problem is this reduced example? – Amfasis Oct 15 '20 at 05:39
  • @Amfasis, _how far from your real problem is this reduced example?_ quite far. In fact the reimplementation of `itemChange` is not just a random guess. In the real case I use `ItemChildAddedChange` to connect the signals of `Foo`'s children of a particular type to `Foo`'s slots. Using a layout inside `Foo` in QML prevents `Foo` from knowing when an item is added, as this item would not be a child of `Foo` anymore, but a child of the layout. So, I need all items as direct children of `Foo`. – scopchanov Oct 15 '20 at 06:03
  • If it's just about the geometry you could opt for writing your own layout: https://blog.rburchell.com/2012/05/writing-layout-in-qml.html or maybe you can draw inspiration from this link – Amfasis Oct 15 '20 at 09:05
  • @Amfasis, thank you for the link! However, that does not help me further, as it describes how to create a layout in QML. I need to know the change in childrens' geometry in a C++ class, which is then use in QML. – scopchanov Oct 15 '20 at 09:27

0 Answers0