JavaScript中 創建動態 QML 對象的方法

一、動態創建對象

有兩種方法可以從 JavaScript 動態創建對象:

  • 調用 Qt.createComponent() 動態創建 Component 對象
  • 使用 Qt.createQmlObject() 從 QML 字符串創建對象

雖然動態創建的對象可以與其他對象一樣使用,但它們在 QML 中沒有 id。

1.1、動態創建組件

可以調用它的 createObject() 方法來創建該組件的一個實例。這個函數可以接受兩個參數:

第一個是新對象的父對象。父對象可以是圖形對象(即 Item 類型)或非圖形對象(即 QtObject 或 C++ QObject 類型)。隻有帶有圖形父對象的圖形對象才會被渲染到 Qt Quick 可視畫佈上。如果希望稍後設置父級,可以安全地將 null 傳遞給此函數。
第二個是可選的,是一個屬性值對的映射,它定義瞭對象的初始任何屬性值。此參數指定的屬性值在對象創建完成之前應用於對象,避免在必須初始化特定屬性以啟用其他屬性綁定時可能發生的綁定錯誤。此外,與在創建對象後定義屬性值和綁定相比,性能優勢很小。
示例。

Sprite.qml 它定義瞭一個簡單的 QML 組件:

import QtQuick 2.0
 
Rectangle { width: 80; height: 50; color: "red" }


main.qml 導入瞭一個 componentCreation.js JavaScript 文件,該文件將創建 Sprite 對象:

import QtQuick 2.0
import "componentCreation.js" as MyScript
 
Rectangle 
{
    id: appWindow
    width: 300; height: 300
 
    Component.onCompleted: MyScript.createSpriteObjects();
}


componentCreation.js

var component;
var sprite;
 
function createSpriteObjects() 
{
    component = Qt.createComponent("Sprite.qml");
    if (component.status == Component.Ready)
        finishCreation();
    else
        component.statusChanged.connect(finishCreation);
}
 
function finishCreation() 
{
    if (component.status == Component.Ready) 
    {
        sprite = component.createObject(appWindow, {x: 100, y: 100});
        if (sprite == null) 
        {
            console.log("Error creating object");
        }
    } 
    else if (component.status == Component.Error) 
    {
        console.log("Error loading component:", component.errorString());
    }
}


當使用帶有相對路徑的文件時,路徑應該是相對於執行 Qt.createComponent() 的文件。

也可以通過 incubateObject() 函數在不阻塞的情況下實例化組件。

1.2、從 QML 字符串創建對象

可以使用 Qt.createQmlObject() 函數從 QML 字符串創建 QML 對象,如下例所示:

const newObject = Qt.createQmlObject(`
    import QtQuick 2.0
    Rectangle 
    {
        color: "red"
        width: 20
        height: 20
    }
    `,
    parentItem,
    "myDynamicSnippet"
);


  • 第一個參數是要創建的 QML 字符串。
  • 第二個參數是新對象的父對象,適用於組件的父參數語義同樣適用於 createQmlObject()
  • 第三個參數是與新對象關聯的文件路徑,這用於錯誤報告。

如果 QML 字符串使用相對路徑導入文件,則路徑應該相對於定義父對象(方法的第二個參數)的文件。

在構建靜態 QML 應用程序時,會掃描 QML 文件以檢測導入依賴項。這樣,所有必要的插件和資源都會在編譯時解決。但是,這僅考慮顯式導入語句(位於 QML 文件頂部的語句),而不考慮包含在字符串文字中的導入語句。為瞭支持靜態構建,用戶需要確保使用 Qt.createQmlObject() 的 QML 文件在文件頂部明確包含所有(包括字符串文字內部)必要的導入。

二、動態刪除對象

在許多用戶界面中,將可視對象的不透明度設置為 0 或將可視對象移出屏幕而不是將其刪除就足夠瞭。 但是,如果有大量動態創建的對象,則刪除未使用的對象可能會獲得有價值的性能優勢。

請註意:永遠不應該手動刪除由便利 QML 對象工廠(例如 Loader 和 Repeater)動態創建的對象。此外,應該避免刪除不是自己動態創建的對象。

可以使用 destroy() 方法刪除項目。 此方法有一個可選參數(默認為 0),用於指定銷毀對象之前的近似延遲(以毫秒為單位)。

示例。application.qml 創建 SelfDestroyingRect.qml 組件的五個實例。 每個實例運行一個 NumberAnimation,當動畫完成時,調用它的根對象上的 destroy() 來銷毀自己:

application.qml   

import QtQuick 2.0
 
Item 
{
    id: container
    width: 500; height: 100
 
    Component.onCompleted: 
    {
        var component = Qt.createComponent("SelfDestroyingRect.qml");
        for (var i=0; i<5; i++) 
        {
            var object = component.createObject(container);
            object.x = (object.width + 10) * i;
        }
    }
}


SelfDestroyingRect.qml

import QtQuick 2.0
 
Rectangle 
{
    id: rect
    width: 80; height: 80
    color: "red"
 
    NumberAnimation on opacity 
    {
        to: 0
        duration: 1000
 
        onRunningChanged: 
        {
            if (!running) 
            {
                console.log("Destroying...")
                rect.destroy();
            }
        }
    }
}
 

或者,application.qml 可以通過調用 object.destroy() 銷毀創建的對象。

請註意:對該對象內的對象調用 destroy() 是安全的。 對象不會在調用 destroy() 的瞬間被銷毀,而是在該腳本塊結束和下一幀之間的某個時間被清除(除非指定瞭非零延遲)。

另請註意,如果 SelfDestroyingRect 實例是像這樣靜態創建的:

Item 
{
    SelfDestroyingRect 
    {
        // ...
    }
}


這會導致錯誤,因為對象隻有在動態創建時才能動態銷毀。

使用 Qt.createQmlObject() 創建的對象可以類似地使用 destroy() 銷毀:

const newObject = Qt.createQmlObject(`
    import QtQuick 2.0
    Rectangle 
    {
        color: "red"
        width: 20
        height: 20
    }
    `,
    parentItem,
    "myDynamicSnippet"
);
newObject.destroy(1000);

到此這篇關於 JavaScript中 創建動態 QML 對象的方法的文章就介紹到這瞭,更多相關 JavaScript 創建動態 QML 對象內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: