How to avoid binding loop when setting padding?

Viewed 97

I want to update the padding of a ScrollView if there is a scrollbar visible, but on the other hand, the visibility of the scrollbar is dependent on the height/width of the content inside the scrollbar, which changes when the padding changes. The following causes a binding loop:

ScrollView {
  id: control
  rightPadding: Scrollbar.vertical.visible ? Scrollbar.vertical.width : 0
   ....


  ScrollBar.vertical: ScrollBar {
    parent: control
    visible: control.height < height
   ...
  }
}

How can I achieve this without a binding loop? Thanks

1 Answers

I was unable to get your code frag to work - it seems like your code should depend on the contents of your ScrollView, but this is not included in your code frag, and it may be missing some other references.

Anyway, I suggest approaching this a little differently - change the ScrollView's content's width based on whether or not the ScrollBar is visible. I also set the ScrollBar policy instead of visibility. I have created a full example where you can add or remove content using a slider for demonstration:

import QtQuick 2.15
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12

ApplicationWindow {
    id: root
    visible: true
    height: 500
    width: 500

    ColumnLayout {
        anchors {
            fill: parent
        }

        Slider {
            // use slider to add delegates to the ScrollView to toggle the scroll bar visibility
            id: slider
            to: 20
        }

        ScrollView {
            id: scroll
            Layout.fillHeight: true
            Layout.fillWidth: true
            ScrollBar.vertical.policy: scrollBarVisible ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff

            property bool scrollBarVisible: scroll.contentHeight > scroll.height

            ColumnLayout {
                width: scroll.scrollBarVisible ? scroll.width - scroll.ScrollBar.vertical.width : scroll.width // change the width of the 

                Repeater {
                    model: slider.value
                    delegate: Rectangle {
                        color: "tomato"
                        Layout.fillWidth: true
                        Layout.preferredHeight: 150
                    }
                }
            }
        }
    }
}

One thing to note though - your ScrollView content cannot have its height depend on its width, for example, if the content had some Text that wraps if there is not enough width, causing it to get taller when the width decreases. This would get back into infinite-loop territory.

Related