7

从 C++ 动态实例化 QML 对象有据可查,但我找不到的是如何使用预先指定的属性值来实例化它。

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

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

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

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

或者,我可以在单独的文件中创建水平和垂直版本,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();

但出乎意料的没有效果。

4

3 回答 3

0

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

特别是,引用QQmlIncubator文档

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

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

默认实现什么也不做。

于 2013-12-31T03:41:43.710 回答
0

我自己的 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 仍然为空!经过一段时间的挖掘,我找到了原因。这对我来说看起来很合理。我改变了我的 QML 课程!

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

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

于 2016-03-02T18:21:40.940 回答
0

对于仍然对此问题感兴趣的任何人,在 Qt 5(以及 Qt 6)中,您还可以使用自定义QQmlContextQQmlContext::setContextProperty()设置外部属性(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);

这应该使您不必摆弄beginCreateand completeCreate

于 2022-02-18T14:10:21.667 回答