Dynamically instantiating a QML object from C++ is well documented , but what I can't find is how to instantiate it with pre-specified values for it's properties.
For example, I am creating a slightly modified SplitView
from C++ like this:
QQmlEngine* engine = QtQml::qmlEngine( this );
QQmlComponent splitComp( engine, QUrl( "qrc:/qml/Sy_splitView.qml" ) );
QObject* splitter = splitComp.create();
splitter->setProperty( "orientation", QVariant::fromValue( orientation ) );
The problem I have is that specifying the orientation
of the SplitView
after it is instantiated causes it's internal layout to break. So, is there a way of creating the SplitView
with the orientation
already specified?
Alternatively I can create both a horizontal and vertical version of SplitView
in separate files and instantiate the appropriate one at runtime - but this is less elegant.
Update
I found 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();
But it had no effect surprisingly.
For anyone still interested in this problem, in Qt 5 (and so Qt 6), you can also use a custom QQmlContext with QQmlContext::setContextProperty()
to setup external property ( orientation
in your case):
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);
This should allow you to not fiddle with beginCreate
and completeCreate
.
Update:
There is also QQmlComponent::createWithInitialProperties() (from 5.14 onwards) that allows you to create an object and initialize its properties before the creation process finishes.
(And then QQmlApplicationEngine::setInitialProperties() is the application engine's version of the same functionality)
I think you should be able to use a custom QQmlIncubator
and the QQmlComponent::create(QQmlIncubator & incubator, QQmlContext * context = 0, QQmlContext * forContext = 0)
factory method.
In particular, quoting from the QQmlIncubator
documentation :
void QQmlIncubator::setInitialState(QObject * object) [virtual protected]
Called after the object is first created, but before property bindings are evaluated and, if applicable, QQmlParserStatus::componentComplete() is called. This is equivalent to the point between QQmlComponent::beginCreate() and QQmlComponent::endCreate(), and can be used to assign initial values to the object's properties.
The default implementation does nothing.
I have had similar situation for my own QML component. Just wanted to init some props before running some bindings. In pure QML I did it that way:
var some = component.createObject(this, {'modelClass': my_model});
From C++ I tried that way:
// 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();
but I had binding errors because modelClass remains null! After digging for a while I found the cause. And it looks reasonable for me. I've changed my QML class!
Item {
id: root
// property var modelClass: null
property var modelClass // just remove : null!
}
Properties with initial values right after invoking beginCreate are not visible from C++, until I call completeCreate(). But if I remove initial value property becomes visible and I can initialize it in C++ code
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.