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. Bidirectional binding properties between QML and Cpp

Bidirectional binding properties between QML and Cpp

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
8 Posts 4 Posters 1.8k Views
  • 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.
  • M Offline
    M Offline
    MartinD
    wrote on last edited by
    #1

    Hi,
    I have a GUI element (e.g. switch) whose state is binded to some Cpp objects property and vice versa, e.g.:

    window.qml:
    MySwitch {
      state: myCppObject.property
      onStateChanged: myCppObject.property = state
    }
    
    MySwitch.qml:
    Item {
      property bool state
      
      MouseArea {
        onCLicked: state= !state
      }
    
      Rectangle {
        color: state ? "black" : white
      }
    }
    

    My implementation (the code above) has one problem. When user clicks the switch ( onCLicked: state = !state is executed) then setting value of the switch from backend stops working (because binding state: myCppObject.property now doesn't exist - at least I think so).

    What is the "nicest" way to make bidirectional bindings?

    ODБOïO 1 Reply Last reply
    0
    • M MartinD

      Hi,
      I have a GUI element (e.g. switch) whose state is binded to some Cpp objects property and vice versa, e.g.:

      window.qml:
      MySwitch {
        state: myCppObject.property
        onStateChanged: myCppObject.property = state
      }
      
      MySwitch.qml:
      Item {
        property bool state
        
        MouseArea {
          onCLicked: state= !state
        }
      
        Rectangle {
          color: state ? "black" : white
        }
      }
      

      My implementation (the code above) has one problem. When user clicks the switch ( onCLicked: state = !state is executed) then setting value of the switch from backend stops working (because binding state: myCppObject.property now doesn't exist - at least I think so).

      What is the "nicest" way to make bidirectional bindings?

      ODБOïO Offline
      ODБOïO Offline
      ODБOï
      wrote on last edited by ODБOï
      #2

      @MartinD hi,

      MySwitch {
        state: myCppObject.property
        // onStateChanged: myCppObject.property = state No need this
      }
      
      
      Item {
        property bool state
        
        MouseArea {
          onClicked : { myCppObject.property = !myCppObject.property } // onCLicked: state= !state
       //do this to your cpp object directly so the QML will follow ..   
        }
      
        Rectangle {
          color: state ? "black" : white
        }
      }
      
      M 1 Reply Last reply
      0
      • ODБOïO ODБOï

        @MartinD hi,

        MySwitch {
          state: myCppObject.property
          // onStateChanged: myCppObject.property = state No need this
        }
        
        
        Item {
          property bool state
          
          MouseArea {
            onClicked : { myCppObject.property = !myCppObject.property } // onCLicked: state= !state
         //do this to your cpp object directly so the QML will follow ..   
          }
        
          Rectangle {
            color: state ? "black" : white
          }
        }
        
        M Offline
        M Offline
        MartinD
        wrote on last edited by
        #3

        @LeLev Thanks. I forgot to mention that MySwitch is reausable component. It is instantiated multiple times throughout my code and binds different properties.

        ODБOïO 1 Reply Last reply
        0
        • M MartinD

          @LeLev Thanks. I forgot to mention that MySwitch is reausable component. It is instantiated multiple times throughout my code and binds different properties.

          ODБOïO Offline
          ODБOïO Offline
          ODБOï
          wrote on last edited by ODБOï
          #4

          @MartinD said in Bidirectional binding properties between QML and Cpp:

          reausable

          then simply emit a signal and catch it in right place to do what ever you need after

          signal tglState()
           MouseArea {
              onClicked : { tglStage() }
            }
          
          1 Reply Last reply
          0
          • M Offline
            M Offline
            MartinD
            wrote on last edited by
            #5

            I tried same thing with QML CheckBox:

            CheckBox {
              text: "CheckBox"
              checked: cppObject.property
              onCheckedChanged: cppObject.property = checked
            }
            

            And again, this doesn't work - checkbox is checked and once something else other than checkbox changes cppObject.property to false, checkbox remains checked.

            How to make bidirectional binding for this checkbox? Pleae also consider that cppObjet can be set to null sometimes and when it is set to valid object checked property of checkbox must be also correctly reevaluated.

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

              @MartinD

              I think in this case, you'll have to forgo binding.

              MySwitch {
                id: sSwitch
                state: myCppObject.property //Now only the initial state during construction
                onStateChanged: myCppObject.property = state
                Connections{
                    target: myCppObject
                    onPropertyChanged: sSwitch.state = property
                }
              }
              

              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.

              M 1 Reply Last reply
              1
              • GrecKoG Offline
                GrecKoG Offline
                GrecKo
                Qt Champions 2018
                wrote on last edited by GrecKo
                #7

                Another way to do it would be to reassign the binding after:

                MySwitch {
                    id: sSwitch
                    state: myCppObject.property
                    onStateChanged: {
                      myCppObject.property = state;
                      state = Qt.binding(() => myCppObject.property);
                    }
                }
                

                Qt Quick Controls 2 do some magic in c++ so that you don't have to rebind. Using a QQC2.Switch and just customizing its appareance would be a solution too.

                1 Reply Last reply
                2
                • J.HilkJ J.Hilk

                  @MartinD

                  I think in this case, you'll have to forgo binding.

                  MySwitch {
                    id: sSwitch
                    state: myCppObject.property //Now only the initial state during construction
                    onStateChanged: myCppObject.property = state
                    Connections{
                        target: myCppObject
                        onPropertyChanged: sSwitch.state = property
                    }
                  }
                  
                  M Offline
                  M Offline
                  MartinD
                  wrote on last edited by
                  #8

                  @J.Hilk Thanks, that will almost work. But it can also happen that myCppObject can be set to null (during that the switch is not valid and e.g. should not be visible to the user) and then myCppObject is set to a valid instance. If myCppObject.property and switch state holds different values then the switch will be in incorrect state. So it seems that I have to write another piece of code to deal with this.

                  Really, is it so difficult in QML to make bidirectional binding? Isn't there any better way?

                  1 Reply Last reply
                  0

                  • Login

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