Qml属性钩子

4
假设有一个名为Test的Qml类型,它有一个foo属性,实现如下: 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
}

以下是使用方法:main.qml

import "."

Test {
    id: _test
}

function baz() {
    var x = _test.foo;
    _test.foo = x;
}

我想要的是每当getter或setter访问foo属性时都能得到通知。对于setter,我可以使用fooChanged信号,但是对于getter没有这样的解决方案。另外,我可以将Test类型实现为一个C++类,使用Q_PROPERTY宏从属性getter/setter中发出相应的信号,但我真的很想将大部分代码留在Qml端。
是否有其他方法来挂钩Qml属性访问?

1
有趣的问题。据我所知,没有直接的方法来做到这一点。无论如何,您可以使用QtObject将变量设置为私有,并在setter/getter中调用自定义信号,就像您在C++中提出的那样,但完全实现在QML中。在我看来,C++版本感觉更加精致。我想这是一个品味的问题。 - BaCaRoZzo
1个回答

6

好的,在经过几个小时的谷歌搜索、阅读Qml和JS文档后,我认为我终于找到了一个解决方案。由于JS在Qml中没有得到完全支持,所以这个解决方案涉及一些技巧,但它仍然有效。主要思路是使用JS的defineProperty方法,动态地向现有对象添加属性。现在我的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
                }
            }
        );
    }
}

main.qml文件中,_test实例声明如下:

property alias _test: _testDeclaration.object

Test {
    id: _testDeclaration
}

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

1
请注意,您可以使用property var object: ({})而不是property var object: { return {}; }。 请参阅http://doc.qt.io/qt-5/qml-var.html#property-value-initialization-semantics。 - Phrogz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接