[SOLVED] childrenRect.height is incorrect if child reduces in size



  • I am attempting to build a ListView, where elements in the View can be expanded if the content exceeds a given constraint, in the example provided, this is simple a toggle on maximumLineCount on a Text component when the row is clicked.

    When the view is originally expanded, the UI behaves as expected, however when the element is clicked again to collapse it, the Text line count correctly updates, but the parent rect is not resized to wrap the content.

    Logging before and after the resize, you can see the childrenRect.height is not correctly recalculated, in fact the onChildrenRectChanged is not called when the child rect reduces in size, only when it grows for the first time.

    main.qml file:

    @import QtQuick 1.1

    Rectangle {
    width: 360
    height: 360

    ListView {
        id: listView
        anchors.fill: parent
    
        model: ListModel {
            ListElement {
                file: "Rect1.qml"
            }
        }
    
        delegate: Item {
            id: listViewDelegate
            width: parent.width
            height: lvLoader.height
    
            Loader {
                anchors {
                    right: parent.right
                    left: parent.left
                    top: parent.top
                }
    
                id: lvLoader
                source: file
            }
    
            Connections {
                target: lvLoader.item
                ignoreUnknownSignals: true
            }
        }
    }
    

    }@

    Expandable list element, Rect1.qml:

    @
    import QtQuick 1.1

    Rectangle {
    id: r1

    anchors {
        left: parent.left
        right: parent.right
    }
    
    color: "red"
    height: childrenRect.height
    
    Text {
        text: "rect1\ntextline2"
        id: t1
        maximumLineCount: 1
    }
    
    Text {
        anchors.top: t1.bottom
        anchors.right: parent.right
        text: "rect1right"
    }
    
    onChildrenRectChanged: {
        console.log("onChildrenRectChanged")
    }
    
    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("pre resize child height: " + r1.childrenRect.height)
    
            if (t1.maximumLineCount === 1) t1.maximumLineCount = 2
            else t1.maximumLineCount = 1
    
            console.log("post resize child height: " + r1.childrenRect.height)
        }
    }
    

    }
    @

    I did consider a work around where I save the collapsed view's height prior to the first expansion, and manually set that as the view height when collapsing again in the future, but this will not work if the user changes the window size.

    I am forced to use QtQuick 1.1 currently due to unfixed "bugs":https://bugreports.qt-project.org/browse/QTBUG-32509 in QtQuick 2.



  • my experience is that childrenRect sometimes doesn't work at all or is always 0 (I use QtQuick 2) for whatever reasons, might be a feature or bug I don't know. Especially if you have some weird anchors and property bindings the Item can be expanded and not collapsed again that is always due to circular bindings I think (the QML engine doesn't always show the warning for that, only for obvious cases)

    Anyway in your case you can just calculate the "childrenRect" yourself if you only have a few items, and don't rely on that property, sometimes that works better if you know the layout of you items it should be easy for a few items to sum up the sizes or whatever depending on your layout.



  • Thanks for the reply Xander.

    Rather than looping the child elements, it seemed simpler to just calculate the height based on the y co-ords of the top of the View, and the lowest element in the view.

    So, Rect1.qml becomes:

    @
    import QtQuick 1.1

    Rectangle {
    id: r1

    anchors {
        left: parent.left
        right: parent.right
    }
    
    color: "red"
    height: (text2.y - r1.y + text2.height)
    
    Text {
        text: "rectext1\ntextline2"
        id: text1
        maximumLineCount: 1
    }
    
    Text {
        id: text2
        anchors.top: text1.bottom
        anchors.right: parent.right
        text: "rectext1right"
    }
    
    onChildrenRectChanged: {
        console.log("onChildrenRectChanged")
    }
    
    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("pre resize child height: " + r1.childrenRect.height)
    
            if (text1.maximumLineCount === 1) text1.maximumLineCount = 2
            else text1.maximumLineCount = 1
    
            console.log("post resize child height: " + r1.childrenRect.height)
        }
    }
    

    }
    @

    This seems like a reasonable work around to me. Once again, thanks for your help.


Log in to reply
 

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