有选择地将C ++核心逻辑暴露给QML的最佳方法

时间:2018-03-20 17:05:59

标签: qt qml

我想设置特定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);

1 个答案:

答案 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();
}