Qml 属性挂钩

bin*_*nzo 4 javascript c++ qt qml

假设有一个Test带有foo属性调用的Qml类型,它的实现如下: Test.qml

// Not necessarily QtObject, but derived from QObject
QtObject {
    // Not necessarily var/property, but must behave like property (i.e. be accessible using "<instance>.foo")
    property var foo
}
Run Code Online (Sandbox Code Playgroud)

并以下列方式使用: main.qml

import "."

Test {
    id: _test
}

function baz() {
    var x = _test.foo;
    _test.foo = x;
}
Run Code Online (Sandbox Code Playgroud)

我想要的是每次foogetter 或 setter 访问属性时都得到通知。对于 setter,也许我可以使用fooChanged信号,但是对于 getter 没有这样的解决方案。我也可以将Test类型实现为C++带有Q_PROPERTY宏的类,并从属性 getter/setter 中发出相应的信号,但我真的很想将大部分代码留在 Qml 端。

还有其他方法可以挂钩 Qml 属性访问吗?

bin*_*nzo 6

好的,经过几个小时的谷歌搜索,阅读 Qml 和 JS 文档,我想我终于找到了解决方案。它涉及一些技巧,因为 Qml 不完全支持 JS,但该解决方案仍然有效。主要思想是使用 JSdefineProperty方法为现有对象动态添加属性。现在我的Test.qml文件看起来像这样:

QtObject {
    // NOTE: .defineProperty does not correctly work for Qml objects, so JS object is used instead
    property var object: { return {}; }

    Component.onCompleted: {
        Object.defineProperty(
            object,
            "foo",
            {
                get: function () {
                    // getter handling here
                },
                set: function (value) {
                    // setter handling here
                }
            }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

并且在main.qml _test实例中声明如下:

property alias _test: _testDeclaration.object

Test {
    id: _testDeclaration
}
Run Code Online (Sandbox Code Playgroud)

希望这个答案能帮助其他人。