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. property binding on object chain

property binding on object chain

Scheduled Pinned Locked Moved Solved QML and Qt Quick
9 Posts 5 Posters 1.4k 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.
  • E Offline
    E Offline
    ebatsin
    wrote on last edited by
    #1

    Hi!

    I am trying to have a Text get the value of a property of a C++ object that can sometimes be null.

    I have 2 C++ objects:

    Project:

    class Project : public QObject {
        Q_OBJECT
    
       Q_PROPERTY(Parameters* parameters READ parameters NOTIFY parametersChanged)
    
      /* definintion of parameters getter/setter/signal. The setter emits the parametersChanged signal */
    };
    

    Parameters:

    class Parameters: public QObject {
        Q_OBJECT
    
        Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    
      /* definintion of name getter/setter/signal. The setter emits the nameChanged signal */
    };
    

    Now, in my QML, I have:

    Text {
        text: myProject.parameters.name
    }
    

    But this does not work. The name is never filled because my project starts with its parameters property set to null. When the property is filled, QML registers it, but after that, if name changes, nothing is happening in QML.

    I tried:

    Text {
        text: myProject.parameters ? myProject.parameters.name : ''
    
        Connections {
            target: myProject:
            onParametersChanged: { console.log('parameters changed') } // emitted and received
        }
    }
    

    My question being: Is there a way to force the binding to be reprocessed entirely when parameters changes so that it will detect that since parameters changed, parameters.name needs to be "re-binded" ?

    Thanks !

    raven-worxR 1 Reply Last reply
    0
    • E ebatsin

      Hi!

      I am trying to have a Text get the value of a property of a C++ object that can sometimes be null.

      I have 2 C++ objects:

      Project:

      class Project : public QObject {
          Q_OBJECT
      
         Q_PROPERTY(Parameters* parameters READ parameters NOTIFY parametersChanged)
      
        /* definintion of parameters getter/setter/signal. The setter emits the parametersChanged signal */
      };
      

      Parameters:

      class Parameters: public QObject {
          Q_OBJECT
      
          Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
      
        /* definintion of name getter/setter/signal. The setter emits the nameChanged signal */
      };
      

      Now, in my QML, I have:

      Text {
          text: myProject.parameters.name
      }
      

      But this does not work. The name is never filled because my project starts with its parameters property set to null. When the property is filled, QML registers it, but after that, if name changes, nothing is happening in QML.

      I tried:

      Text {
          text: myProject.parameters ? myProject.parameters.name : ''
      
          Connections {
              target: myProject:
              onParametersChanged: { console.log('parameters changed') } // emitted and received
          }
      }
      

      My question being: Is there a way to force the binding to be reprocessed entirely when parameters changes so that it will detect that since parameters changed, parameters.name needs to be "re-binded" ?

      Thanks !

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by raven-worx
      #2

      @ebatsin said in property binding on object chain:
      "nested" properties do not emit such a binding, you could try a Binding element

       Text {
              id: t
              Binding {
                  when: myProject.parameters
                   value: myProject.parameters.name
                    target: t
                   property: "text"
              }
      }
      

      (untested)

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      1
      • fcarneyF Offline
        fcarneyF Offline
        fcarney
        wrote on last edited by
        #3

        @ebatsin said in property binding on object chain:

        The name is never filled

        Are you explicitly emitting the signals when you change the value in C++? Are you changed it in C++, QML, or both?

        C++ is a perfectly valid school of magic.

        1 Reply Last reply
        0
        • E Offline
          E Offline
          ebatsin
          wrote on last edited by ebatsin
          #4

          @raven-worx
          Thanks, this works in the case I explained previously (depth 2 nesting) but I get an error at the value line of the binding in QML (even though it works):
          TypeError: Cannot read property 'name' of null

          But is there a way that would be robust to something like that: project.parameters.angles.roll where both parameters and angles could be null be null ?

          Since I can't do:

          Text {
              id: t
              Binding {
                  when: project.parameters.angles // do not work when parameters is null
                  ....
              }
          }
          

          This is more of a theorical question since I do not expect this problem to happen in my use case.
          Also, is there somewhere documentation/blog post/article that explains why nested properties bindings are not re-evaluated if one part of the nested chains changes (ie: parameters goes from null to a valid pointer) ?

          @fcarney
          The signals are explicitly emitted when the value is changed:

          	void Project::setParameters(Parameters* parameters) {
          		if(d->parameters != parameters) {
          			d->parameters = parameters;
          			emit parametersChanged();
          		}
          	}
          
          	void Parameters::setName(QString const& name) {
          		if(d->name != name) {
          			d->name = name;
          
          			emit nameChanged();
          		}
          	}
          

          The values are changed exclusively from C++ (controlled by a QStateMachine)

          Thanks for your help :)

          raven-worxR 1 Reply Last reply
          0
          • E ebatsin

            @raven-worx
            Thanks, this works in the case I explained previously (depth 2 nesting) but I get an error at the value line of the binding in QML (even though it works):
            TypeError: Cannot read property 'name' of null

            But is there a way that would be robust to something like that: project.parameters.angles.roll where both parameters and angles could be null be null ?

            Since I can't do:

            Text {
                id: t
                Binding {
                    when: project.parameters.angles // do not work when parameters is null
                    ....
                }
            }
            

            This is more of a theorical question since I do not expect this problem to happen in my use case.
            Also, is there somewhere documentation/blog post/article that explains why nested properties bindings are not re-evaluated if one part of the nested chains changes (ie: parameters goes from null to a valid pointer) ?

            @fcarney
            The signals are explicitly emitted when the value is changed:

            	void Project::setParameters(Parameters* parameters) {
            		if(d->parameters != parameters) {
            			d->parameters = parameters;
            			emit parametersChanged();
            		}
            	}
            
            	void Parameters::setName(QString const& name) {
            		if(d->name != name) {
            			d->name = name;
            
            			emit nameChanged();
            		}
            	}
            

            The values are changed exclusively from C++ (controlled by a QStateMachine)

            Thanks for your help :)

            raven-worxR Offline
            raven-worxR Offline
            raven-worx
            Moderators
            wrote on last edited by
            #5

            @ebatsin said in property binding on object chain:

            But is there a way that would be robust to something like that: project.parameters.angles.roll where both parameters and angles could be null be null ?
            Since I can't do:
            Text {
            id: t
            Binding {
            when: project.parameters.angles // do not work when parameters is null
            ....
            }
            }

             Binding {
                    when: project.parameters && project.parameters.angles
            }
            

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            E 1 Reply Last reply
            3
            • raven-worxR raven-worx

              @ebatsin said in property binding on object chain:

              But is there a way that would be robust to something like that: project.parameters.angles.roll where both parameters and angles could be null be null ?
              Since I can't do:
              Text {
              id: t
              Binding {
              when: project.parameters.angles // do not work when parameters is null
              ....
              }
              }

               Binding {
                      when: project.parameters && project.parameters.angles
              }
              
              E Offline
              E Offline
              ebatsin
              wrote on last edited by
              #6

              @raven-worx Indeed. Should have found that one alone :/

              I still get an error when the QML is parsed which is not really sexy in my application logs (but the binding works so I'll call it a win for now).

              As I said before, is there somewhere that explains why nested bindings are not re-evaluated if a property in the middle of the chain changes ?

              raven-worxR 1 Reply Last reply
              0
              • E ebatsin

                @raven-worx Indeed. Should have found that one alone :/

                I still get an error when the QML is parsed which is not really sexy in my application logs (but the binding works so I'll call it a win for now).

                As I said before, is there somewhere that explains why nested bindings are not re-evaluated if a property in the middle of the chain changes ?

                raven-worxR Offline
                raven-worxR Offline
                raven-worx
                Moderators
                wrote on last edited by
                #7

                @ebatsin said in property binding on object chain:

                As I said before, is there somewhere that explains why nested bindings are not re-evaluated if a property in the middle of the chain changes ?

                i am not aware of an explaination of this behavior.
                But i am thinking of the following:
                A triggering of the the parent property might notify other bindings even if actually nothing has changed for that particular binding

                --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                If you have a question please use the forum so others can benefit from the solution in the future

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

                  You could just do :

                  Text {
                      text: myProject.parameters && myProject.parameters.name || ""
                  }
                  

                  Nested properties ARE re-evaluated if a property in the middle of the chain changes.

                  D 1 Reply Last reply
                  0
                  • GrecKoG GrecKo

                    You could just do :

                    Text {
                        text: myProject.parameters && myProject.parameters.name || ""
                    }
                    

                    Nested properties ARE re-evaluated if a property in the middle of the chain changes.

                    D Offline
                    D Offline
                    Duc V Nguyen
                    wrote on last edited by
                    #9

                    @GrecKo This won't work. Although changing parameters will make the text to be re-eavaluted, changing of the nested property name won't trigger the text to be re-evaluated. It is because initially the expression bind to the name property of the old parameters instance.

                    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