Bypassing binding loops



  • I've got a timeline UI where basically each element is positioned based on some model data. For instance the x coordinate is based on the seconds and the width is based on the duration of the element.
    @
    width: modelData.duration * pixelSecondWidth
    x: modelData.seconds * pixelSecondWidth + 1
    @

    Then I try to use a MouseArea to drag the element around or drag handles at the beginning and end of the element. The problem I have is that if I use @onXChanged@ to store the seconds back into the modelData I get a binding loop. If I don't, then the element moves fine but the value doesn't update (obviously).

    So I can think of three potential ways to do this:

    Is there a way of setting the width without creating a binding?

    Can I somehow create an intermediate step inbetween that handles the conversion between seconds and duration to coordinates and back without messing with the C++ model?

    Is there some way to get the mouse delta rather than mouse position during a drag?



  • Setting a property using an assignment will do without binding

    @Component.onCompleted: width = modelData.duration * pixelSecondWidth@



  • What I've ended up with is
    @
    Component.onCompleted: {
    width = modelData.duration * pixelSecondWidth
    x = modelData.seconds * pixelSecondWidth + 1
    }

        Connections {
            target: modelData
            onDurationChanged: {
                if (!mouse.drag.active)
                {
                    property.width = modelData.duration * pixelSecondWidth
                }
            }
    
            onSecondsChanged: {
                if (!mouse.drag.active)
                {
                    property.x = modelData.seconds * pixelSecondWidth + 1
                }
            }
        }
    
        onWidthChanged: {
            if(mouse.drag.active)
                modelData.duration = width / pixelSecondWidth
        }
    
        onXChanged: {
            if (mouse.drag.active)
                modelData.seconds = (x - 1) / pixelSecondWidth
        }
    

    @

    I figure there must be a way to do this with Bindings somehow. May play around later. Thinking something like:
    @
    Binding on width { when: mouse.drag.active; value: ...}
    @


Log in to reply
 

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