簡體   English   中英

從具有指定屬性的 C++ 創建 QML object

[英]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 ) );

我遇到的問題是在實例化指定SplitVieworientation會導致其內部布局中斷。 那么,有沒有一種方法可以創建已指定orientationSplitView

或者,我可以在單獨的文件中同時創建水平和垂直版本的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);

這應該允許您不擺弄beginCreatecompleteCreate

更新:

還有QQmlComponent::createWithInitialProperties() (從 5.14 開始)允許您創建一個 object 並在創建過程完成之前初始化其屬性。

(然后QQmlApplicationEngine::setInitialProperties()是具有相同功能的應用程序引擎版本)

我認為你應該可以使用自定義QQmlIncubatorQQmlComponent::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM