QML動態創建自定義組件


一、動態加載和實例化對象:createComponent

例子1:

①、創建本地的QML文件,注意文件第一個字母要大寫

ZStation.qml

import QtQuick 2.5

Rectangle{
    property string mName: "station"
    signal entered(string objName);
    signal exited();
    property int station_width: width/3

    id: root
    color: Qt.rgba(0,0,0,0)
    width: 90
    height: width/3
    Rectangle{
        id: station
        color:"green"
        width: station_width
        height: width
        radius: width/2
    }
    Text {
        anchors.top:parent.top;
        anchors.left: station.right;
        anchors.leftMargin: 5;
        width: 30
        height: 12
        text: mName
        color: "white"
    }
    MouseArea {
        hoverEnabled: true;
        anchors.fill: parent;
        onEntered: {
            root.entered(root.objectName);
        }
        onExited: {
            root.exited();
        }
    }
}

②、在主qml里動態創建並連接信號槽

function addStation(x, y, id, name){
    console.log(x,y,id,name);
    var componentIn = Qt.createComponent("ZStation.qml");
    if (componentIn.status === Component.Ready) {
        var objIn = componentIn.createObject(root, {"mName":name, "objectName":id});
        if(auto_scale){
            x = getNearX(x);
            y = getNearY(y);
        }

        objIn.x = x;
        objIn.y = y;
        objIn.entered.connect(root.showPopInfo)
        objIn.exited.connect(root.hidePopInfo)
        station_list.push(objIn);
        console.log(x,y);
    }else{
        console.log("qml create station err:",componentIn.errorString());
    }
}

 

例子2:

①、main.qml

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id: mainWin
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    LoginPage {
        width: 300
        height: 200
        anchors.centerIn: parent
    }
}

②、LoginPage.qml

import QtQuick 2.0
import QtQuick.Controls 2.3

Rectangle {
    id: loginPage
    width: 400
    height: 300
    color: "#051f58"
    radius: 8
    clip:true

    Button {
        text: "登錄頁面-登錄按鈕"
        anchors.centerIn: parent
        onClicked: {
            // 隱藏登錄頁面
            loginPage.visible = false // 不能銷毀,否則下面的"主頁面"也會跟隨銷毀,則后面
            // 點擊"主頁面-關閉按鈕",將無法銷毀關閉"主頁面"

            // 在主窗口(mainWin)上顯示主頁面
            var compMainPage = Qt.createComponent("MainPage.qml")
            .createObject(mainWin, {x:50, y:50, width:200, height:250});
        }
    }
}

③、MainPage.qml

import QtQuick 2.0
import QtQuick.Controls 2.3

Rectangle {
    id: mainPage
    color: "#498ff8"
    radius: 8

    Button {
        text: "主頁面-關閉按鈕"
        anchors.centerIn: parent
        onClicked: {
            // 銷毀關閉主頁面
            mainPage.destroy()
        }
    }
}

參考:https://www.cnblogs.com/linuxAndMcu/p/13566502.html

 

PS: 

①、createComponent的返回值

 

 ②、創建過程時間是不確定的,我們上面的例子都是直接創建並判斷狀態,大多數情況是沒問題,但是遇到特殊情況如:加載多種依賴或位於緩慢服務器中的QML時,會很慢【而且貌似創建函數不會阻塞】,故正確做法是:加一個判斷

function createImageObject() {
    component = Qt.createComponent("dynamic-image.qml");
    if (component.status === Component.Ready || component.status === Component.Error) {
        finishCreation();
    } else {
        component.statusChanged.connect(finishCreation);
    }
}

function finishCreation() {
    if (component.status === Component.Ready) {
        var image = component.createObject(root, {"x": 100, "y": 100});
        if (image === null) {
            console.log("Error creating image");
        }
    } else if (component.status === Component.Error) {
        console.log("Error loading component:", component.errorString());
    }
}

例子位於QMLBook的第15章節,動態創建組件。

③、銷毀

item=Qt.createQmlObject(...);
... item.destroy();

 

二、動態創建Component

這個方式和上面原理一致,component1是事先定義好的Component

 Component.onCompleted: {
        var obj1 = component1.createObject(root, { "color": "red", "width": 100, "height": 100})
        var obj2 = component2.createObject(root, { "color": "green", "width": 200, "height": 200})
        var obj3 = component3.createObject(root, { "color": "gray", "width": 300, "height": 300})
    }

 

 

三、從文本文件動態實例化:createQmlObject

1、接口

 

 qml:qml文本

 parent:對象的父親

 filepath:存儲創建對象時的錯誤報告

 返回:立即返回創建的對象或null,這是與上面其他接口不一樣的:

 

 

2、例子1:

import QtQuick 2.5

Item {
    id: root

    width: 1024
    height: 600

    function createItem() {
        Qt.createQmlObject("import QtQuick 2.5; Rectangle { x: 100; y: 100; width: 100; height: 100; color: \"blue\" }", root, "dynamicItem");
    }

    Component.onCompleted: root.createItem();
}

 

四、createComponent

createComponent其實和createObject一樣,除了createComponent多了一個指定是否同步創建的參數,可以認為就是一個createObject,這里不加例子了

 

 如圖,多了mode參數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM