我想设置特定QML组件的上下文属性,而不是在根上下文中。我不希望在组件外部访问该属性。从C ++是否有一种方法可以访问组件的上下文,以仅允许从组件的上下文中而不是从全局命名空间访问命名属性?我想保持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);
您应该实现一个单例,该单例仅在导入位置可见。这是将核心逻辑暴露给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 不能真正信任在更动态的使用上下文中管理对象的生存期。
// 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();
}