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: ...}
@