我想设置特定QML组件的上下文属性,而不是在根上下文中。我不希望该属性在组件外部可访问。有没有办法从C ++访问Component的上下文,只允许从组件的上下文中访问命名属性,而不是从全局命名空间访问?我想保留QML声明,不要用C ++创建组件来访问它的上下文。
//main.qml
Item {
Button {
// this should NOT work
text: ctxProp.text
}
OtherQml {
}
}
//OtherQml.qml
Item {
Button {
// this should work
text: ctxProp.text
}
}
//main.cpp
QGuiApplication app(art, argv);
QQmlQpplicationEngine engine;
// Some QObject Type
CtxProp ctxProp;
// I'd like to set the context such that only OtherQml.qml can access
// this context propery. Setting in root context property makes it global
engine.rootContext()->setContextProperty("ctxProp", &ctxProp);
答案 0 :(得分:5)
您应该实现一个仅在导入位置可见的单例。这是将核心逻辑暴露给QML的最佳和最有效的解决方案,因为不涉及树查找,并且只有在您选择导入它时才可见。
qmlRegisterSingletonType<CtxProp>("Sys", 1, 0, "Core", getCoreFoo);
// and in QML
import Sys 1.0
...
doStuffWith(Core.text)
getCoreFoo
是一个返回CtxProp *
值的函数的名称(由于元数据的使用,任何QObject *
实际上都会这样做)。您可以在函数中创建它,或者只返回指向现有实例的指针。有些人声称如果函数没有创建它可能会出现问题,因为它可能是由QML引擎管理的,但是我一直在使用一个预先存在的函数,我在多个QML引擎中共享并且没有它的问题,当然是明确地将所有权设置为C ++,因为QML cannot really be trusted在更动态的使用环境中管理对象的生命周期。
// main.cpp
static Core * c;
static QObject * getCore(QQmlEngine *, QJSEngine *) { return c; }
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
c = new Core; // create
engine.setObjectOwnership(c, QQmlEngine::CppOwnership); // don't manage
qmlRegisterSingletonType<Core>("Sys", 1, 0, "Core", getCore); // reg singleton
engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); // load main qml
return app.exec();
}