Динамическое создание объекта QML из C ++ хорошо задокументированы, но что я не могу найти, так это как создать его экземпляр с заранее заданными значениями для его свойств.
Например, я создаю слегка модифицированный 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 ) );
У меня проблема в том, что указание orientation
из SplitView
после это создает экземпляр его внутреннего макета, чтобы сломаться. Итак, есть ли способ создания SplitView
с orientation
уже указано?
В качестве альтернативы я могу создать как горизонтальную, так и вертикальную версию 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();
Но это не имело удивительного эффекта.
Я думаю, что вы должны иметь возможность использовать обычай 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 остается нулевым! Немного покопавшись я нашел причину. И это выглядит разумно для меня. Я изменил свой класс QML!
Item {
id: root
// property var modelClass: null
property var modelClass // just remove : null!
}
Свойства с начальными значениями сразу после вызова beginCreate не видны из C ++, пока я не вызову completeCreate (). Но если я удаляю начальное значение, свойство становится видимым, и я могу инициализировать его в коде C ++