Qt 6.5文档翻译:Qt QML/将C++中的状态信息暴露给QML模块,Exposing State from C++ to QML
我们通常会需要将C++模块中的某些属性暴露给:某个特定组件中的全部QML 元素;某个模块中的全部QML 元素;甚至就是所有模块中全部的QML 元素。你可以采用两种方法来达到这一目的:引入单实例对象;或是向选定的组件的根对象添加属性。
如果你想向某个模块中的全部元素暴露一些全局属性,甚至就是想要向任何模块中全部的元素暴露一些全局属性,那么,你可以在C++代码中定义一个单实例对象。具体的做法就是,向某个类的定义中加入QML_ELEMENT或QML_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 元素来暴露某些属性,那么,你可以将它们添加为该组件的根元素的常规属性。为了确保它们的值一定会被设置,你可以将它们声明为 必需属性 。具体可在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),并且在内层对象中通过标识符和名字来访问该属性。为了确保根元素的标识符能够在任何嵌套组件中访问到,我们使用了组件行为定义(ComponentBehavior)。
接下来,在C++中,每当你创建这种组件的一个对象时,你就必须使用QQmlComponent::createWithInitialProperties、QQmlApplicationEngine::setInitialProperties或QQuickView::setInitialProperties来对指定的属性进行初始化。例如:
QQmlEngine engine;
QQmlComponent component(&engine, "MyModule" , "RequiredProperties" );
QScopedPointer < QObject > o(component.createWithInitialProperties({
{ "thing" , 11 }
}));
这里,我们假设,你的模块的标识地址(URI)是MyModule,并且该模块可以通过QML 引用路径访问到。
HxLauncher: Launch Android applications by voice commands