Ред и начин на оценки на обвързване на свойства в QML

Доколкото разбирам, когато свойствата се използват в обвързващи изрази, техните NOTIFY сигнали са свързани, за да сигнализират за преоценка на израза всеки път, когато стойността на свойство се промени.

Така че разгледайте този тривиален пример:

Rectangle {
    width: 200
    height: width - 100

    Text {
        text: "value is " + (parent.width + parent.height)
    }
}

В него свойството height е обвързано със свойството width, а свойството text е обвързано и с двете.

В този пример не е ясно какъв е редът на действие. Искам да кажа, че ако width се промени, той ще издаде, за да преоцени и двата израза, които го препращат. Но width също ще промени height, което също ще задейства оценка на text.

Следователно свойството text оценява ли се два пъти? Веднъж, когато width се промени, и още веднъж, когато width промени height? Или може би QML има някакъв механизъм за оптимизиране на това поведение, като например сигналите за уведомяване не задействат действителна преоценка, а само маркират изразите като „мръсни“ и те се преоценяват при следващата итерация на цикъла на събитието, когато цялото сигнализиране е разпространено? И дори да е така, как двигателят ще знае да актуализира height преди да актуализира text, за да избегне двойната преоценка на последния? Или може би връзката е директна, а не на опашка, и се използва някакъв по-сложен механизъм, за да се разбере редът на преоценка? Или може би няма нищо подобно и text може действително да преоцени два пъти, ако случайно това е произволният ред?

Наистина трябва да разбера как работи това, защото имам проект, в който модифицирам множество свойства на множество QML обекти от страна на C++ по императивен начин, които са обвързани от страната на QML и получавам много непоследователно и непостоянно поведение, така че определено трябва да се вземе предвид начина, по който работят.


person Community    schedule 20.11.2014    source източник


Отговори (1)


да изглежда, че сте прав и text ще бъде актуализиран два пъти. Простият пример:

Rectangle {
    id: testRect
    width: 200
    height: width - 100

    Text {
        text: "value is " + (parent.width + parent.height)
        onTextChanged: {
            console.log("text was changed (" + parent.width + "," + parent.height + ")");
        }
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            testRect.width = 300
        }
    }
}

изход:

qml: text was changed (200,100) 
qml: text was changed (300,100) 
qml: text was changed (300,200)

Предполагам, че това е просто поведение и актуализира съответното свойство, когато промени някои свойства, на които се основава този елемент.

Qt docs съвети за избягване на подобна ситуация - However, if a binding is overly complex - such as involving multiple lines, or imperative loops - it could indicate that the binding is being used for more than describing property relationships. Complex bindings can reduce code performance, readability, and maintainability. It may be a good idea to redesign components that have complex bindings, or at least factor the binding out into a separate function.

person folibis    schedule 20.11.2014
comment
Намерих kdab.com/qml-engine-internals-part-2 -bindings в раздела за коментари FYI: При първото зареждане на компонента QML машината ще се опита да оцени обвързванията в ред, който минимизира преоценките на обвързването, но предполагам, че няма голяма стойност, тъй като не успява дори в такива прости случаи като горния пример. Това изглежда изненадващо непрофесионално за Qt... - person ; 21.11.2014