c++ - Q_PROPERTY NOTIFY 信号及其参数

标签 c++ qt data-binding binding qml

我习惯用参数编写我的“propertyChanged”signal,这样接收端就不需要调用Q_PROPERTYREAD 功能显式。

我这样做是为了清楚起见,并假设在 QML 数据绑定(bind)情况下,不需要对 getter 进行“昂贵的”调用来实际获取值,因为它已经作为信号参数传递给 QML。

我的同事不同意并说这违反了“QML 风格”,对此我的回应是文档明确指出它可能有一个参数将采用底层成员的新值:

NOTIFY signals for MEMBER variables must take zero or one parameter, which must be of the same type as the property. The parameter will take the new value of the property.

文档中没有任何地方指出 QML 绑定(bind)系统使用此参数来防止在处理信号时对 getter 进行额外的函数调用。我知道这个调用可能是从 C++ 进行的,因此不会进行“昂贵”的 QML 到 C++ 调用,但它仍然是一个额外的函数调用,原则上在许多更新的情况下可能会导致明显的性能损失。

我尝试检查 QML 绑定(bind)源代码,但无法从中推断出任何信息。我想知道是否有人知道这是怎么回事:是否使用了信号参数?

最佳答案

I wonder if someone knows what the deal is: is the signal argument used or not?

这是一种检查方法:

#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"

ma​​in.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

所以可以肯定地说使用的是值而不是 getter。

若要查看未使用信号参数时的输出结果,请取消注释掉的行并注释掉另一行:

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

关于c++ - Q_PROPERTY NOTIFY 信号及其参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43705363/

相关文章:

c++ - 复制字符串直到 '.' 以及当我知道结构时如何只复制数字

C++将文本文件中的文本作为单个字符放入数组中

c++ - 系统托盘中的菜单没有每个 QActions

android - Qt Android 构建 SSL 错误

QT:正常的VS项目文件要构建吗?

c# - 通过 .NET 中的某种接口(interface)使属性可用于数据绑定(bind)?

Android NDK 找不到-lGLESv

c++ - 如何使用 luajit 在带有变量参数的 c 函数中获取 cdata?

Grails 数据绑定(bind)和 transient

c# - 如何在没有代码隐藏的情况下实现 OnPreviewMouseDown?