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. Order of QML property's dependency evaluation
QtWS25 Last Chance

Order of QML property's dependency evaluation

Scheduled Pinned Locked Moved Solved QML and Qt Quick
qmlbindingproperties
5 Posts 2 Posters 1.5k 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.
  • B Offline
    B Offline
    b-arun-kumar
    wrote on 15 Dec 2021, 11:15 last edited by
    #1

    I have a CustomQMLComponent. It has 3 properties. p3 is dependent on p1 & p2. p1 & p2 are set when an instance of CustomQMLComponent is created.

    Questions:

    1. By the time p3 is evaluated, will p1 & p2 always have the values set by the caller.
    2. What is the recommended way to set p3, as shown below or as in the commented statement?

    CustomQMLComponent.qml:

    Item {
    	required property string p1
            property bool p2 : false
    	property int p3: cppContextPropertyObj.slot(p1, p2)
    	//Component.onCompleted: p3 = cppContextPropertyObj.slot(p1, p2)
    }
    

    main.qml:

    CustomQMLComponent{
        p1: "my_string"
        p2: true
    }
    
    1 Reply Last reply
    0
    • S Offline
      S Offline
      sierdzio
      Moderators
      wrote on 15 Dec 2021, 12:00 last edited by
      #2

      In QML there is no order of evaluation. The language is declarative, meaning: when p1 changes, all other properties depending on it will change, too. When p2 changes, all other properties depending on it will change.

      So in you example, p3 will be calculated at least twice initially. QML engine does go through properties in the order of their creation, but that is an implementation detail, you should never depend on it.

      To answer your second question: if you want p3 to update dynamically based on changes of p1 and p2, you have to use a binding (as you have it now). If you want to set it only once and not update later, use the solution you have commented out.

      (Z(:^

      B 1 Reply Last reply 15 Dec 2021, 14:06
      0
      • S sierdzio
        15 Dec 2021, 12:00

        In QML there is no order of evaluation. The language is declarative, meaning: when p1 changes, all other properties depending on it will change, too. When p2 changes, all other properties depending on it will change.

        So in you example, p3 will be calculated at least twice initially. QML engine does go through properties in the order of their creation, but that is an implementation detail, you should never depend on it.

        To answer your second question: if you want p3 to update dynamically based on changes of p1 and p2, you have to use a binding (as you have it now). If you want to set it only once and not update later, use the solution you have commented out.

        B Offline
        B Offline
        b-arun-kumar
        wrote on 15 Dec 2021, 14:06 last edited by b-arun-kumar
        #3

        @sierdzio

        p1 and p2 have static value assignments, whereas p3 has a binding value assignment.

        As per this old article: https://www.kdab.com/qml-engine-internals-part-2-bindings/, static value assignments happen during creation phase and binding value assignments happen at the end of creation phase.

        Case 1:

        CustomQMLComponent{}
        

        In this case, based on the above article, p1 & p2 values are set by the time p3 value is set.

        Case 2:

        CustomQMLComponent{
            p1: "my_string"
            p2: true
        }
        

        What happens in this case?

        In a more general sense, what happens when properties of a component are set when creating an instance of the component? Are the properties initialized with default values and then overridden by the new instance's values? Or, the properties are initialized just once with the default/new values.

        B 1 Reply Last reply 20 Dec 2021, 12:48
        0
        • S Offline
          S Offline
          sierdzio
          Moderators
          wrote on 15 Dec 2021, 20:30 last edited by
          #4

          I don't know, but you can easily check this: just add some logs:

          Item {
          	required property string p1
                  property bool p2 : false
          	property int p3: cppContextPropertyObj.slot(p1, p2)
          	//Component.onCompleted: p3 = cppContextPropertyObj.slot(p1, p2)
          
            onP1Changed: console.log("P1 changed to:", p1)
            onP2Changed: console.log("P2 changed to:", p2)
            onP3Changed: console.log("P3 changed to:", p3)
          }
          

          As I mentioned though, in practice it does not matter what exactly happens.

          (Z(:^

          1 Reply Last reply
          0
          • B b-arun-kumar
            15 Dec 2021, 14:06

            @sierdzio

            p1 and p2 have static value assignments, whereas p3 has a binding value assignment.

            As per this old article: https://www.kdab.com/qml-engine-internals-part-2-bindings/, static value assignments happen during creation phase and binding value assignments happen at the end of creation phase.

            Case 1:

            CustomQMLComponent{}
            

            In this case, based on the above article, p1 & p2 values are set by the time p3 value is set.

            Case 2:

            CustomQMLComponent{
                p1: "my_string"
                p2: true
            }
            

            What happens in this case?

            In a more general sense, what happens when properties of a component are set when creating an instance of the component? Are the properties initialized with default values and then overridden by the new instance's values? Or, the properties are initialized just once with the default/new values.

            B Offline
            B Offline
            b-arun-kumar
            wrote on 20 Dec 2021, 12:48 last edited by
            #5

            @b-arun-kumar said in Order of QML property's dependency evaluation:
            Response from Qt Support:

            As per this old article: https://www.kdab.com/qml-engine-internals-part-2-bindings/, static value assignments happen during creation phase and binding value assignments happen at the end of creation phase.

            That is how it should be, literals first, then functions. But it is not actually documented so in theory it could change. This is also only true for simple literal assignments. Anything even slightly hinting about complexity makes QML engine postpone them together with all those needing the evaluation. For example it happens if you wrap the value with {} like this: p2: {true}

            Case 1:

            CustomQMLComponent{}
            

            In this case, based on the above article, p1 & p2 values are set by the time p3 value is set.

            The order in which these "static" properties are set is undefined and also the order in which more complex expressions are done are undefined. So it is best to avoid making assumptions about the order.

            Case 2:

            CustomQMLComponent{
                p1: "my_string"
                p2: true
            }
            

            What happens in this case?

            In a more general sense, what happens when properties of a component are set when creating an instance of the component? Are the properties initialized with default values and then overridden by the new instance's values? Or, the properties are initialized just once with the default/new values.

            Just once. Although the properties do of course have some default value before the value in QML is assigned. The initial value set in constructor of a C++ class, or in case of QML defined property, default constructed value of the type (empty string, 0, false or null in case it is QObject* type).

            And why this could be important is because something like onXXXChanged signals are handled immediately when they occur and thus it could be ran before all those "static" assignment are done. Consider for example:

            onP1Changed: if (p2) {...} else {...}

            QML engine does not know that there is some dependency to p2 on p1 value change and in case p1 gets assigned before p2, this could take unexpected path and if p2 value change is not explicitly also handled properly in this case, could lead to mismatched state.

            1 Reply Last reply
            1

            5/5

            20 Dec 2021, 12:48

            • Login

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