Q_PROPERTY NOTIFY Signal and Its Argument

I have the habit of writing my "propertyChanged" signalwith an argument, so the receiving end does not need to explicitly call the function Q_PROPERTY READ.

I do this from clarity and the assumption that in a QML data binding situation, an “expensive” getter call is not required to actually retrieve the value, since it has already been passed to QML as a signal argument.

My colleagues did not agree and stated that this was contrary to the “QML style” to which I replied, the documentation clearly states that it can have an argument that will take on a new value for the base element:

NOTIFYsignals for variables MEMBERmust accept zero or one parameter, which must be of the same type as the property. The parameter will accept the new value of the property.

Nowhere in the documentation is it indicated that the QML binding system uses this parameter to prevent an additional function call when received by a signal. I understand that this call is likely to be made from C ++, so there will be no expensive QML call in C ++, but it is still an additional function call, which in principle can lead to a noticeable performance decrease in the case of many updates.

I tried to check the source code of the QML binding, but could not deduce anything from it. I wonder if someone knows what a deal is: is the signal argument used or not?

+4
3

, QML "" , , QML .

, - , . . , , .

QML , . QML , , , - , , . , , , , , getters .

, . , , , . , . , , , .

, MEMBER, , , .

, , , . , .

, , ++, , QML. , , , . - ++, - , ++ ( ), QML , .

, . " QML", , , " QML" - . , , , , .

+2

, -, : ?

:

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QDebug>

class MyType : public QObject
{
    Q_OBJECT
    Q_PROPERTY(bool foo READ foo WRITE setFoo NOTIFY fooChanged)

public:
    MyType(QObject *parent = nullptr) :
        QObject(parent),
        mFoo(0)
    {
    }

    bool foo() const
    {
        qDebug() << Q_FUNC_INFO;
        return mFoo;
    }

    void setFoo(bool foo)
    {
        if (foo == mFoo)
            return;

        mFoo = foo;
        emit fooChanged(mFoo);
    }

signals:
    void fooChanged(bool foo);

private:
    bool mFoo;
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);

    qmlRegisterType<MyType>("App", 1, 0, "MyType");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    return app.exec();
}

#include "main.moc"

main.qml:

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.0

import App 1.0

Window {
    width: 400
    height: 400
    visible: true

    Switch {
        id: fooSwitch
    }

    MyType {
        id: myType
        foo: fooSwitch.checked
        onFooChanged: print("onFooChanged, foo =", foo)
//        onFooChanged: print("onFooChanged myType.foo =", myType.foo)
    }
}

:

qml: onFooChanged, foo = true
qml: onFooChanged, foo = false

, , .

, , , :

bool __cdecl MyType::foo(void) const
qml: onFooChanged myType.foo = true
bool __cdecl MyType::foo(void) const
qml: onFooChanged myType.foo = false
+2

onPropertyChanged -, , QML.

, , , , , , , .

basictypes.qml

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    id: root
    visible: true
    width: 400; height: 450

    property int num: 5
    Button {
        text: num
        onClicked: num += 1
    }
    onNumChanged: console.log(JSON.stringify(arguments), arguments.length)
}

, , , int.

QML , , , . , false, , ?

, onPropertyChanged realse , , QML property [type] [name], . ( : text, width, height).

+1

Source: https://habr.com/ru/post/1676019/


All Articles