Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
qtws26_logo

The Qt Event of the Year: Qt World Summit 2026

Save Your Spot >
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. C++ QProperty binding Question
Qt 6.12 LTS is out! See what's new in the release blog

C++ QProperty binding Question

Scheduled Pinned Locked Moved Solved QML and Qt Quick
14 Posts 5 Posters 2.4k 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.
  • JonBJ JonB

    @dheerendra
    Just a quick answer from me, I don't use QML so you may get a better answer from someone who does, I don't want to take up too much space.

    https://doc.qt.io/qt-6/qtqml-syntax-propertybinding.html does say:

    When a property's dependencies change in value, the property is automatically updated according to the specified relationship.

    Behind the scenes, the QML engine monitors the property's dependencies (that is, the variables in the binding expression). When a change is detected, the QML engine re-evaluates the binding expression and applies the new result to the property.

    And the example in https://doc.qt.io/qt-6/qtqml-syntax-propertybinding.html#using-keyword-this-keyword-with-property-binding does say

    To bind the Rectangle's height to its own width, the binding expression must explicitly refer to this.width (or alternatively, rect.width):

    This does imply to me that QML builds a "graph" for a binding which specifies each base property it references so it knows when to recalculate.

    dheerendraD Offline
    dheerendraD Offline
    dheerendra
    Moderators Qt Champions 2024 Qt Champions 2022 Qt Champions 2017
    wrote on last edited by
    #5

    @JonB
    Thanks Jon. QML I have clarity.

    This is C++ code binding introduced in Qt 6+. Property binding in C++. This lamda expression confused me. I can write any code inside the lambda. I can refer the variables in side. Do something else etc. So how binding is built with variable which are referred in side the lambda.

    Dheerendra
    @Community Service
    Certified Qt Specialist
    https://www.pthinks.com

    JonBJ J.HilkJ 2 Replies Last reply
    0
    • dheerendraD dheerendra

      @JonB
      Thanks Jon. QML I have clarity.

      This is C++ code binding introduced in Qt 6+. Property binding in C++. This lamda expression confused me. I can write any code inside the lambda. I can refer the variables in side. Do something else etc. So how binding is built with variable which are referred in side the lambda.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #6

      @dheerendra
      Well, I've jumped in here erroneously already so why not stick my head out further?

      Formulating a Property Binding still talks about

      Any C++ expression evaluating to the correct type can be used as a binding expression and be given to the setBinding() method. However, to formulate a correct binding, some rules must be followed.

      Dependency tracking only works on bindable properties. It's the developer's responsibility to ensure that all properties used in the binding expression are bindable properties. When non-bindable properties are used in a binding expression, changes to those properties do not trigger updates to the bound property. No warning or error is generated either at compile-time or at run-time. The bound property will be updated only when bindable properties used in the binding expression are changed

      So we are still talking about "tracking bindable properties in an expression" to decide whether the expression's value has changed. Per your template <typename Functor> QPropertyBinding<T> QProperty::setBinding(Functor f)

      The property's value is set to the result of evaluating the new binding. Whenever a dependency of the binding changes, the binding will be re-evaluated, and the property's value gets updated accordingly.

      I think the code really does see that you are accessing other properties and so update. But i really will shut up now, as you probably guessed this too!

      OK, finally I think this really does say it: under Qt Bindable Properties

      Qt provides bindable properties. Bindable properties are properties which either have a value or are specified using any C++ function, typically a C++ lambda expression. In case they are specified using a C++ function, they are updated automatically whenever their dependencies change.

      1 Reply Last reply
      1
      • dheerendraD dheerendra

        @JonB
        Thanks Jon. QML I have clarity.

        This is C++ code binding introduced in Qt 6+. Property binding in C++. This lamda expression confused me. I can write any code inside the lambda. I can refer the variables in side. Do something else etc. So how binding is built with variable which are referred in side the lambda.

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #7

        @dheerendra

        cough cough My voice is not my own:

        The setBinding function itself doesn't directly analyze the lambda body or "know" about the variables width and height. Instead, the QProperty class provides a mechanism for registering dependencies between properties.

        When you call setBinding, you're essentially telling the QProperty object that the value of this property (area in your case) depends on the values of other properties, namely width and height.

        The lambda expression you provide is a function that calculates the value of the area property based on the values of width and height. However, it's not the lambda expression itself that the QProperty object "understands" or keeps track of; it's the fact that you've registered a dependency on width and height.

        Internally, when you call setBinding, the QProperty object can inspect the lambda expression and identify any external variables that are captured by reference. In your lambda & { return width * height; }, width and height are captured by reference (&), indicating that they are external variables used inside the lambda body.

        Once the QProperty object identifies these external variables, it stores them as dependencies for the property. So, whenever the values of these dependencies change (i.e., when width or height changes), the QProperty object knows that it needs to re-evaluate the binding function associated with the property.

        In essence, the QProperty class provides a mechanism for tracking dependencies between properties based on the information you provide when you set up bindings. It doesn't directly analyze the lambda body or "understand" the variables used inside it; it simply keeps track of the dependencies you specify.


        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.

        JonBJ GrecKoG 2 Replies Last reply
        2
        • J.HilkJ J.Hilk

          @dheerendra

          cough cough My voice is not my own:

          The setBinding function itself doesn't directly analyze the lambda body or "know" about the variables width and height. Instead, the QProperty class provides a mechanism for registering dependencies between properties.

          When you call setBinding, you're essentially telling the QProperty object that the value of this property (area in your case) depends on the values of other properties, namely width and height.

          The lambda expression you provide is a function that calculates the value of the area property based on the values of width and height. However, it's not the lambda expression itself that the QProperty object "understands" or keeps track of; it's the fact that you've registered a dependency on width and height.

          Internally, when you call setBinding, the QProperty object can inspect the lambda expression and identify any external variables that are captured by reference. In your lambda & { return width * height; }, width and height are captured by reference (&), indicating that they are external variables used inside the lambda body.

          Once the QProperty object identifies these external variables, it stores them as dependencies for the property. So, whenever the values of these dependencies change (i.e., when width or height changes), the QProperty object knows that it needs to re-evaluate the binding function associated with the property.

          In essence, the QProperty class provides a mechanism for tracking dependencies between properties based on the information you provide when you set up bindings. It doesn't directly analyze the lambda body or "understand" the variables used inside it; it simply keeps track of the dependencies you specify.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #8

          @J-Hilk said in C++ QProperty binding Question:

          Internally, when you call setBinding, the QProperty object can inspect the lambda expression and identify any external variables that are captured by reference.

          Once the QProperty object identifies these external variables, it stores them as dependencies for the property.

          Exactly! But how does it have access to do that? The C++ lambda is compiled into code by the time it gets passed to setBinding(), is it not, so what calls are available to say "what variables/properties are referenced in this compiled C++ expression/functor"? I guess "reflection" somehow, but how does it even see that width or height are in the expression once it's compiled?

          P.S.
          Are these "Qt Bindable Properties" new at Qt6, so I (Qt5) cannot even play with them?

          dheerendraD 1 Reply Last reply
          0
          • JonBJ JonB

            @J-Hilk said in C++ QProperty binding Question:

            Internally, when you call setBinding, the QProperty object can inspect the lambda expression and identify any external variables that are captured by reference.

            Once the QProperty object identifies these external variables, it stores them as dependencies for the property.

            Exactly! But how does it have access to do that? The C++ lambda is compiled into code by the time it gets passed to setBinding(), is it not, so what calls are available to say "what variables/properties are referenced in this compiled C++ expression/functor"? I guess "reflection" somehow, but how does it even see that width or height are in the expression once it's compiled?

            P.S.
            Are these "Qt Bindable Properties" new at Qt6, so I (Qt5) cannot even play with them?

            dheerendraD Offline
            dheerendraD Offline
            dheerendra
            Moderators Qt Champions 2024 Qt Champions 2022 Qt Champions 2017
            wrote on last edited by
            #9

            @JonB @J-Hilk

            Thank you. Yes QProperty is doing this. Unless some scanning of lambda happens it cannot achieve this. When does this happen ? How does it happen ? Some code scanning must happen. Is there some preprocessing like Moc. I know moc is not doing.

            Any way code works. I have imagined like oh something happens like this. However when what how etc were not clear.

            Dheerendra
            @Community Service
            Certified Qt Specialist
            https://www.pthinks.com

            jsulmJ 1 Reply Last reply
            0
            • dheerendraD dheerendra

              @JonB @J-Hilk

              Thank you. Yes QProperty is doing this. Unless some scanning of lambda happens it cannot achieve this. When does this happen ? How does it happen ? Some code scanning must happen. Is there some preprocessing like Moc. I know moc is not doing.

              Any way code works. I have imagined like oh something happens like this. However when what how etc were not clear.

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #10

              @dheerendra Qt is open source you can look in the code to see how this overload of setBinding works

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • dheerendraD dheerendra

                Following is the code snippet. Code is working properly. No issue with code. I have understanding issue. How this internally works.

                QProperty<int> height { 50};
                 QProperty<int> width { 100};
                
                 QProperty<int> area;
                 area.setBinding([&](){
                     qDebug() << " This is called one more time" << Qt::endl;
                     return width * height;
                 });
                
                 width = 4;
                 height = 40;
                 width = 10;
                

                How the change in width or height triggers the re-evaluate of area ?
                Area is binded to lambda expression. Inside the lambda we have reference to width & height. How the notify(change) signal of width or height is bound to area ? Is there any parsing happens for lambda expression, finds the width or height & then it does the some thing ?
                Looking for an answer on binding is built internally.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #11

                @dheerendra
                May I suggest you try this.

                • To your properties add QProperty<int> dummy { 42 };
                • To your lambda add qDebug() << "area being recalculated";.

                Now try altering the value of dummy, only. Does the qDebug() get called?

                • If it does then re-evaluation is not tied to the fact that the lambda only accesses width & height, it looks like a change to any property triggers re-evaluation. I'm kind of hoping it works this way, bad for efficiency, good for understanding!

                • If it does not get called then somehow Qt has figured out that the lambda accesses only certain variables/properties, and I'm not sure how it dos that from code.

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

                  @dheerendra

                  cough cough My voice is not my own:

                  The setBinding function itself doesn't directly analyze the lambda body or "know" about the variables width and height. Instead, the QProperty class provides a mechanism for registering dependencies between properties.

                  When you call setBinding, you're essentially telling the QProperty object that the value of this property (area in your case) depends on the values of other properties, namely width and height.

                  The lambda expression you provide is a function that calculates the value of the area property based on the values of width and height. However, it's not the lambda expression itself that the QProperty object "understands" or keeps track of; it's the fact that you've registered a dependency on width and height.

                  Internally, when you call setBinding, the QProperty object can inspect the lambda expression and identify any external variables that are captured by reference. In your lambda & { return width * height; }, width and height are captured by reference (&), indicating that they are external variables used inside the lambda body.

                  Once the QProperty object identifies these external variables, it stores them as dependencies for the property. So, whenever the values of these dependencies change (i.e., when width or height changes), the QProperty object knows that it needs to re-evaluate the binding function associated with the property.

                  In essence, the QProperty class provides a mechanism for tracking dependencies between properties based on the information you provide when you set up bindings. It doesn't directly analyze the lambda body or "understand" the variables used inside it; it simply keeps track of the dependencies you specify.

                  GrecKoG Offline
                  GrecKoG Offline
                  GrecKo
                  Qt Champions 2018
                  wrote on last edited by GrecKo
                  #12

                  @J-Hilk said in C++ QProperty binding Question:

                  Internally, when you call setBinding, the QProperty object can inspect the lambda expression and identify any external variables that are captured by reference. In your lambda & { return width * height; }, width and height are captured by reference (&), indicating that they are external variables used inside the lambda body.

                  No.

                  The QProperty knows its dependency because when you call setBinding with a lambda, the lambda is executed and it tracks the other properties that are being evaluated in it.

                  If both width and height are QProperty<int>.
                  width * height is first calling the implicit QProperty<int>::operator int() for both, converting them to int so it can call the arithmetic operator * on their values. This operator int() is what is registering the dependency.

                  To put it otherwise, when calling area.setBinding([&](){ return width * height; }); here is what happens:

                  • the lambda is stored in the area QProperty to be called later.
                  • area is marked as the current property being evaluated.
                  • the lambda is then executed.
                    • width is being accessed through its conversion operator, it is thus being registered as a dependency of the currently evaluated property (area here)
                    • the same happens for height
                  • the return value of the lambda is assigned to area
                  • area is no longer marked as the currently evaluated property.

                  After that, every time that width and height are changed, the lambda is being reevaluated and the above process redone.

                  JonBJ dheerendraD 2 Replies Last reply
                  3
                  • GrecKoG GrecKo

                    @J-Hilk said in C++ QProperty binding Question:

                    Internally, when you call setBinding, the QProperty object can inspect the lambda expression and identify any external variables that are captured by reference. In your lambda & { return width * height; }, width and height are captured by reference (&), indicating that they are external variables used inside the lambda body.

                    No.

                    The QProperty knows its dependency because when you call setBinding with a lambda, the lambda is executed and it tracks the other properties that are being evaluated in it.

                    If both width and height are QProperty<int>.
                    width * height is first calling the implicit QProperty<int>::operator int() for both, converting them to int so it can call the arithmetic operator * on their values. This operator int() is what is registering the dependency.

                    To put it otherwise, when calling area.setBinding([&](){ return width * height; }); here is what happens:

                    • the lambda is stored in the area QProperty to be called later.
                    • area is marked as the current property being evaluated.
                    • the lambda is then executed.
                      • width is being accessed through its conversion operator, it is thus being registered as a dependency of the currently evaluated property (area here)
                      • the same happens for height
                    • the return value of the lambda is assigned to area
                    • area is no longer marked as the currently evaluated property.

                    After that, every time that width and height are changed, the lambda is being reevaluated and the above process redone.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #13

                    @GrecKo said in C++ QProperty binding Question:

                    width * height is first calling the implicit QProperty<int>::operator int() for both, converting them to int so it can call the arithmetic operator * on their values. This operator int() is what is registering the dependency.

                    [My italics.] Wow! OK, that answers the question as to how it gets at the dependencies without "analyzing" code, which it couldn't really do from C++. But that means there must be this or an equivalent for every possible operation you could do on a QProperty. Makes you wonder if you find some expression involving a QProperty which cannot be "tracked" like this, but I guess not.

                    1 Reply Last reply
                    1
                    • GrecKoG GrecKo

                      @J-Hilk said in C++ QProperty binding Question:

                      Internally, when you call setBinding, the QProperty object can inspect the lambda expression and identify any external variables that are captured by reference. In your lambda & { return width * height; }, width and height are captured by reference (&), indicating that they are external variables used inside the lambda body.

                      No.

                      The QProperty knows its dependency because when you call setBinding with a lambda, the lambda is executed and it tracks the other properties that are being evaluated in it.

                      If both width and height are QProperty<int>.
                      width * height is first calling the implicit QProperty<int>::operator int() for both, converting them to int so it can call the arithmetic operator * on their values. This operator int() is what is registering the dependency.

                      To put it otherwise, when calling area.setBinding([&](){ return width * height; }); here is what happens:

                      • the lambda is stored in the area QProperty to be called later.
                      • area is marked as the current property being evaluated.
                      • the lambda is then executed.
                        • width is being accessed through its conversion operator, it is thus being registered as a dependency of the currently evaluated property (area here)
                        • the same happens for height
                      • the return value of the lambda is assigned to area
                      • area is no longer marked as the currently evaluated property.

                      After that, every time that width and height are changed, the lambda is being reevaluated and the above process redone.

                      dheerendraD Offline
                      dheerendraD Offline
                      dheerendra
                      Moderators Qt Champions 2024 Qt Champions 2022 Qt Champions 2017
                      wrote on last edited by
                      #14

                      @GrecKo said in C++ QProperty binding Question:

                      the lambda is then executed.

                      Thanks GrecKo. This clears my thought process. Lambda is getting executed the moment you do the setBinding.

                      Dheerendra
                      @Community Service
                      Certified Qt Specialist
                      https://www.pthinks.com

                      1 Reply Last reply
                      1
                      • dheerendraD dheerendra has marked this topic as solved on

                      • Login

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