[英]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.