Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Controls appear to break bindings when interacted with

Controls appear to break bindings when interacted with

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
4 Posts 4 Posters 401 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    sissow2
    wrote on last edited by
    #1

    For example, a basic checkbox:

    CheckBox {
        checked: model.value
        onClicked: model.maybe_change_value_maybe_not_depends_on_complex_business_logic();
    }
    

    What I expect this means is checked is now bound to model.value, and must never deviate from model.value. Unfortunately it can. Note my verbosely named function: sometimes the value is changed, but when it isnt the property cannot notify and thus the checkbox becomes desynced. In this state, checked is observably different from model.value!! I cannot just do checked = model.value in the slot for onClicked because that breaks the binding completely. I instead have to do janky stuff like this:

    CheckBox {
        property int evil_hacky_hack: 0
        checked: evil_hacky_hack, model.value
        onClicked: {
            model.maybe_change_value_maybe_not_depends_on_complex_business_logic();
            ++evil_hacky_hack // Force a re-evaluate
        }
    }
    

    Note that I've observed this happening with other stateful control types, like TextField (with editingFinished). This leads me to believe that it's a conscious design choice instead of a bug.

    So I guess my question here: Am I missing a better supported, more scalable way to do this that's applicable to all controls? Is there a way to make CheckBox (and Qml's controls in general) a pure view for my model data without significant skulduggery? It's infeasible (and inadvisable, imo) to change my model to notify when a change doesn't happen.

    Qt 5.9 if it matters; I'm not sure what to search for in changelogs to check for fixes (or how to try this in Qt6). Also my first post here, lmk if this belongs elsewhere.

    1 Reply Last reply
    1
    • I Offline
      I Offline
      IHaber
      wrote on last edited by
      #2

      I dont know if this helps you now, since noone has responded... but the way i solve this (and i've had to do it on multiple ui elements) is as follows:

      • Create custom qml type where the base item is the same as the original (CheckBox in this case)
      • Add property var checkedBinding
      • Add Component.onCompleted:{if(typeof checkedBinding==='function' checked=Qt.binding(checkedBinding)}
      • Add onClicked:{if(typeof checkedBinding==='function' checked=Qt.binding(checkedBinding)}

      Then when using the component, instead of setting checked:model.value you can use checkedBinding:function(){return model.value}

      This is really annoying behavior and i wish qt would fix it. it's not as bad in this simple case, but it can cause a lot of issues when you are doing multiple components put together with custom behavior. The example that bothers me the most is making a DoubleSpinbox item , since the act of changing the binding itself to handle doubles automatically conflicts with using the element itself (even ignoring outside bindings) and will thus automatically unbind itself from the original implementation of the double spin box.

      1 Reply Last reply
      1
      • L Offline
        L Offline
        leadbelly
        wrote last edited by
        #3

        I strongly agree that this behaviour should be regarded as a bug. If a component (QtQuick.Controls.Button in this case) exposes a mutable property then this implicitly communicates that a client should be able to bind to that property without the binding being overwritten by internal behaviour of the control.

        (Short of Qt fixing this bug) the more idiomatic fix is probably to reimplement Button yourself, by deriving QtQuick.Templates.Control and ensuring that no public bindings are ever internally overwritten. The problem then is that many other controls in the QtQuick.Controls module expect a QtQuick.Controls.Button in their API and therefore would also need reimplementing to accept your new well behaved button type.. before you know it you're reimplimenting the whole module ! Yeah.. not great.

        1 Reply Last reply
        0
        • J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote last edited by
          #4

          By default, Qt Quick Controls CheckBox updates its checkState when the user interacts with it
          (and cycles through states when tristate is enabled). That write breaks a checked: model.value
          binding, so if your business logic rejects the change and does not update model.value, the UI can
          stay desynced.

          Option 1: handle onToggled and re-establish the binding (and optionally snap back immediately):

          CheckBox {
              id: cb
              checked: model.value
          
              onToggled: function(wanted) {
                  model.maybe_change_value_maybe_not_depends_on_complex_business_logic(wanted)
          
                   if (model.value !== wanted) {
                      cb.checked = Qt.binding(function() { return model.value })
                  }
              }
          }
          

          Option 2: override nextCheckState so the control never toggles itself:

          CheckBox {
              checked: model.value
          
              onClicked: model.maybe_change_value_maybe_not_depends_on_complex_business_logic()
          
              nextCheckState: function() {
                  return model.value ? Qt.Checked : Qt.Unchecked
              }
          }
          

          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved