从 C++ 暴露状态到 QML

通常希望从 C++ 暴露一些属性,以便在特定组件中的所有 QML 元素、模块中的所有 QML 元素甚至是所有的 QML 元素可以使用。您可以通过引入单例或者向选定组件的根对象添加属性来实现。

使用单例

如果您想将多个全局属性暴露给模块中的所有元素或所有元素整体,您可以在 C++ 中定义一个单例。为此,请将 QML_ELEMENTQML_NAMED_ELEMENT 宏以及 QML_SINGLETON 宏添加到包含要暴露为 Q_PROPERTY 声明的属性的类中

// Singleton.h
class Singleton : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int thing READ thing WRITE setThing NOTIFY thingChanged FINAL)
    QML_ELEMENT
    QML_SINGLETON

public:
    Singleton(QObject *parent = nullptr) : QObject(parent) {}

    int thing() const { return m_value; }
    void setThing(int v)
    {
        if (v != m_value) {
            m_value = v;
            emit thingChanged();
        }
    }

signals:
    void thingChanged();

private:
    int m_value = 12;
};

现在您可以通过从任何导入此模块的 QML 代码中访问单例的 thing 属性

import QtQml

QtObject {
    objectName: "The thing is " + Singleton.thing
}

如果您将您的 QML 文件放在与模块相同的目录中(强烈推荐),则在您的模块内部隐式导入它时可用。您不需要显式导入任何内容。如果不这样的话,或者您想从模块中访问 thing 属性,您需要导入单例所属的模块。

为了从 C++ 中设置属性值,您可能需要检索单例实例。为此,您可以使用 QQmlEngine::singletonInstance。首选的方法是将模块和类型名称作为参数传递

    Singleton *singleton
            = engine->singletonInstance<Singleton *>("MyModule", "Singleton");
    singleton->setThing(77);

使用对象属性

如果您想仅将属性暴露给特定组件中的 QML 元素,您可以将它们作为常规属性添加到组件的根对象上。为了确保它们在所有情况下都真正设置,您可以将其设置为 Required Properties。您可能将您的 QML 组件编写如下

pragma ComponentBehavior: Bound

import QtQuick

Window {
    id: root
    visible: true

    required property int thing

    Text {
        anchors.fill: parent
        text: "The thing is " + root.thing
    }

    component Inner: QtObject {
        objectName: "I can see " + root.thing + " because I'm bound."
    }
}

我们为组件的根元素使用了 ID,并从任何内部对象通过 ID 和名称进行属性引用。为了安全地将根元素的 ID 传递到任何嵌套组件中,我们使用了 ComponentBehavior

然后,在 C++ 中,当您从此类组件创建对象时,您需要确保调用 QQmlComponent::createWithInitialPropertiesQQmlApplicationEngine::setInitialPropertiesQQuickView::setInitialProperties 来初始化属性。例如

    QQmlEngine engine;

    QQmlComponent component(&engine, "MyModule", "RequiredProperties");
    QScopedPointer<QObject> o(component.createWithInitialProperties({
            {"thing", 11}
    }));

这假设您的模块 URI 是 MyModule,并且该模块在 QML 导入路径中可用。

© 2024 Qt公司有限公司。本文件的文档贡献属于各所有者的版权。本文档受自由软件基金会发布的GNU自由文档许可协议版本1.3的条款约束。Qt及其相关标志是芬兰及其它国家和地区Qt公司的商标。所有其他商标均为其各自所有者的财产。