0

The user of my application can click and drag on an image to select a region of interest. I also want a TextField where the user can manually tweak the values, but I've been having trouble getting the bindings to work.

My first attempted looked like

Column {
    property ROI roi
    Label { text: "Minimum X" }
    TextField {id: min_x; text: roi.pointMin.x}
}

This correctly displays the current x coordinate in the text field. However, when I edit the text field, the position isn't updated. I can correct this with the following code.

Column {
    property ROI roi
    Label { text: "Minimum X" }
    TextField {id: min_x; text: roi.pointMin.x}
    Binding {
        target: roi
        property: "pointMin.x"
        value: min_x.text;
    }
}

This correctly establishes that bidirectional binding that updates both when the user draws a new region of interest and when the user updates the via the TextField. However, the log is spammed with messages about the presence of a binding loop. It's very obvious where the binding loop is, but how can I remove it without losing the functionality?

On the off chance that it matters, roi.pointMin is a QPoint.

EDIT: One crucial point that I hadn't mentioned was that I've been trying to remain completely declarative and avoid event handlers. That rules out many other solutions presented on the site, but may be an impossible ask.

rprospero
  • 913
  • 11
  • 26
  • 1
    Does this answer your question? [Two way binding C++ model in QML](https://stackoverflow.com/questions/41232999/two-way-binding-c-model-in-qml) – JarMan Apr 21 '22 at 13:32
  • @JarMan I did read that and it's how I came up with my Binding solution in the first place. I'd been trying to remain completely declarative and not bind to events, which is part of the solution on that page, but my aversion might be misplaced. – rprospero Apr 21 '22 at 14:09

1 Answers1

2

For this specific purpose you can use textEdited() of the TextField to detect changes from the user input, instead of binding to the text property.

Column {
    property ROI roi
    Label { text: "Minimum X" }
    TextField {
        id: min_x; 
        text: roi.pointMin.x
        onTextEdited: function() {
            roi.pointMin.x = min_x.text
        }
    }
}
Soheil Armin
  • 2,725
  • 1
  • 6
  • 18
  • I'd been attempting to remain declarative and avoid specifically binding to events, but I'm beginning to think that I'm fighting QML instead of working with it. – rprospero Apr 21 '22 at 14:07
  • 2
    @rprospero It still looks declarative to me. Events are there to be used like this. it does not break any rules or it is not against any *best practice* to use them like this. – Soheil Armin Apr 21 '22 at 14:15