[英]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 ) );
我遇到的问题是在实例化后指定SplitView
的orientation
会导致其内部布局中断。 那么,有没有一种方法可以创建已指定orientation
的SplitView
?
或者,我可以在单独的文件中同时创建水平和垂直版本的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);
这应该允许您不摆弄beginCreate
和completeCreate
。
更新:
还有QQmlComponent::createWithInitialProperties() (从 5.14 开始)允许您创建一个 object 并在创建过程完成之前初始化其属性。
(然后QQmlApplicationEngine::setInitialProperties()是具有相同功能的应用程序引擎版本)
我认为你应该可以使用自定义QQmlIncubator
和QQmlComponent::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.