繁体   English   中英

从具有指定属性的 C++ 创建 QML object

[英]Create QML object from C++ with specified properties

从 C++ 动态实例化 QML object 有详细记录,但我找不到的是如何使用预先指定的属性值实例化它。

例如,我正在从 C++ 创建一个稍微修改过的SplitView ,如下所示:

QQmlEngine* engine = QtQml::qmlEngine( this );
QQmlComponent splitComp( engine, QUrl( "qrc:/qml/Sy_splitView.qml" ) );
QObject* splitter = splitComp.create();

splitter->setProperty( "orientation", QVariant::fromValue( orientation ) );

我遇到的问题是在实例化指定SplitVieworientation会导致其内部布局中断。 那么,有没有一种方法可以创建已指定orientationSplitView

或者,我可以在单独的文件中同时创建水平和垂直版本的SplitView ,并在运行时实例化适当的版本——但这不太优雅。

更新

我找到QQmlComponent::beginCreate(QQmlContext* publicContext)

QQmlEngine* engine = QtQml::qmlEngine( this );
QQmlComponent splitComp( engine, QUrl( "qrc:/qml/Sy_splitView.qml" ) );
QObject* splitter = splitComp.beginCreate( engine->contextForObject( this ) );

splitter->setProperty( "orientation", QVariant::fromValue( orientation ) );
splitter->setParent( parent() );
splitter->setProperty( "parent", QVariant::fromValue( parent() ) );
splitComp.completeCreate();

但出乎意料的是没有效果。

对于仍然对此问题感兴趣的任何人,在 Qt 5(以及 Qt 6)中,您还可以使用带有QQmlContext::setContextProperty()的自定义QQmlContext来设置外部属性(在您的情况下为orientation ):

QQmlEngine engine;

QQmlContext *context = new QQmlContext(engine.rootContext());
context->setContextProperty("myCustomOrientation", QVariant::fromValue(orientation));

// you can use a 'myCustomOrientation' property inside Sy_splitView.qml, e.g.
// `orientation: myCustomOrientation`
QQmlComponent splitComp(&engine, QUrl("qrc:/qml/Sy_splitView.qml"));
QObject* splitter = splitComp.create(context);

这应该允许您不摆弄beginCreatecompleteCreate

更新:

还有QQmlComponent::createWithInitialProperties() (从 5.14 开始)允许您创建一个 object 并在创建过程完成之前初始化其属性。

(然后QQmlApplicationEngine::setInitialProperties()是具有相同功能的应用程序引擎版本)

我认为你应该可以使用自定义QQmlIncubatorQQmlComponent::create(QQmlIncubator & incubator, QQmlContext * context = 0, QQmlContext * forContext = 0)工厂方法。

特别是,引用QQmlIncubator文档

void QQmlIncubator :: setInitialState(QObject * object)[虚拟保护]

在首次创建对象之后调用,但在评估属性绑定之前调用,如果适用,则调用QQmlParserStatus :: componentComplete()。 这相当于QQmlComponent :: beginCreate()和QQmlComponent :: endCreate()之间的点,可用于为对象的属性分配初始值。

默认实现什么都不做。

我对自己的QML组件有类似的情况。 只是想在运行一些绑定之前初始化一些道具。 在纯QML中,我这样做:

var some = component.createObject(this, {'modelClass': my_model});

从C ++我尝试了这样:

// create ui object
auto uiObject = qobject_cast<QQuickItem*>(component.beginCreate(ctx));
// place on ui
uiObject->setParentItem(cont);

// set model properties
classInstance->setView(QVariant::fromValue(uiObject));
classInstance->setPosition(QPointF(x, y));

// set ui object properties
uiObject->setProperty("modelClass", QVariant::fromValue(classInstance.get()));

// finish
component.completeCreate();

但我有绑定错误,因为modelClass仍然为null! 经过一段时间的挖掘后,我找到了原因。 对我来说这看起来很合理。 我改变了我的QML课程!

Item {
    id: root
    // property var modelClass: null
    property var modelClass // just remove : null!
}

在调用completeCreate()之后,在调用beginCreate之后,具有初始值的属性在C ++中是不可见的。 但是,如果我删除初始值属性变得可见,我可以在C ++代码中初始化它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM