qtbindingqmlqtquick2qtquickcontrols

Slider element keeps resetting target value to slider's minimum value


There is a self contained example of the problem:

Rectangle {
    id: rect
    width: 200
    height: 200
    property real v : 50
    onVChanged: console.log(v)
    Button {
        onClicked: scomp.createObject(rect)
    }
    Component {
        id: scomp
        Rectangle {
            id: sli
            anchors.fill: parent
            Column {
                Slider {
                    width: 200
                    minimumValue: 10
                    maximumValue: 100
                    value: rect.v
                    onValueChanged: rect.v = value
                }
                Button {
                    onClicked: sli.destroy()
                }
            }
        }
    }
}

Basically, every time the slider component is created to modify v it sets it to the slider's minimum value. Note that the slider will still work correctly to modify that value, and v will retain its proper value after the slider is closed, but the moment it is opened again, the value corrupts again.

Why is this happening, how to prevent it? It would seem that for some explainable reason, the slider's value property temporarily assumes its minimumValue value, but that doesn't look like adequate behaviour. Maybe a bug? The slider never really assumes the correct initial value, even if value: rect.v is moved before setting the minimum value.


Solution

  • Without digging in the implementation of the Slider element, it seems that the implementation order has been poorly designed, the initial value is 0.0, so setting the minimum value to anything higher pushes up the value as well. And it doesn't matter if value is bound to something higher than the minimum value, due to the order of evaluation, the value is always 0.0 when minimum value is set, so in this format the target value will always be corrupted to the slider's minimum value.

    The solution I came up with avoids this behavior by delaying the target value binding, it works, but it is not as pretty, so I am still open to other solutions, meanwhile Qt guys - if you are seeing this you might wanna fix the Slider:

    Slider {
        width: 200
        minimumValue: 10
        maximumValue: 100
        value: rect.v
        Component.onCompleted: valueChanged.connect(function(){ rect.v = value})
    }
    

    This format still initially pushes the slider value to the minimum value, but at this time the binding to set the target value does not exist yet, it is only created after the slider value assumes the correct value.