1. 程式人生 > >8.QML中的元件Component

8.QML中的元件Component

本篇文章介紹一下QML中的元件,Component

1. 使用Component在QML中嵌入元件

Component是Qt框架或者開發者封裝好的、只暴露必要介面的QML型別,可以重複使用。要再QML中嵌入Component的定義,需要使用Component物件。

  • Component只能包含一個頂層的Item,而且在這個Item之外不能定義任何的資料,除了Id。
  • Component通常用來給一個View提供圖形化元件。
  • Component不是Item的派生類,而是從QQmlComponent繼承而來的,雖然它通過自己的頂層Item為其他的View提供視覺化元件,但它本身不是可見元素。

下面是一個簡單的在QML文件中定義Component的示例:

Component {
    id: itemCompont
    Rectangle {
        id: compontRect
        color: 'blue'
        implicitWidth: 200
        implicitHeight: 50

        signal deleteThis()

        Text {
            id: interText
            anchors.left: parent.left
            anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter text: qsTr("text")
} Button { anchors.margins: 5 anchors.top: parent.top anchors.bottom: parent.bottom anchors.right: parent.right text: '刪除' onClicked: { compontRect.deleteThis()
} } } }

2. 在檔案中定義元件

很多時候我們把QML檔案定義在一個檔案中,方便被其他的QML檔案呼叫。可以直接使用檔名作為元件的名稱,在其他的QML檔案中使用。上面元件中的程式碼可以單獨定義在一個檔案中,本示例的檔名為TestCompont.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4

Rectangle {
    id: compontRect
    color: Qt.rgba(0.8, 0.4, 0.4, 1.0)
    implicitWidth: 200
    implicitHeight: 50
    property var currentObject: ''

    signal deleteThis(var obj)

    // 設定文字的內容
    function setCurrentText(textName) {
        interText.text = textName
    }

    Text {
        id: interText
        anchors.left: parent.left
        anchors.leftMargin: 10
        anchors.verticalCenter: parent.verticalCenter
        text: qsTr("text")
    }
    Button {
        anchors.margins: 5
        anchors.top: parent.top
        anchors.bottom: parent.bottom
        anchors.right: parent.right
        text: '刪除'

        onClicked: {
            compontRect.deleteThis(compontRect)
        }
    }

    Component.onCompleted: {
        compontRect.currentObject = parent
    }
}

3. 使用Loader載入/刪除元件

Loader用來動態載入QML元件。

  • source屬性,載入一個QML文件。
  • sourceComponent屬性,載入一個Component物件。
  • sourcesourceComponent屬性發生變化時,它之前的物件會被銷燬,新物件會被載入。
  • source設定為空串,或者sourceComponent設定為undefined,將會銷燬當前物件,相關資源也會被釋放,Loader物件會變成一個空物件。
  • item屬性指向他載入的元件的頂層Item,比如上面的示例item就為Rectangle

下面是一個使用Loader載入/刪除元件的一個示例,效果如下:
Loader
上面的紅色Item為直接使用Component的Loader,下面為從檔案中載入的元件。
程式碼如下:

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4

Window {
    width: 800
    height: 600
    visible: true

    Rectangle {
        id: mainRect
        anchors.fill: parent

        Loader {
            id: loader1
            sourceComponent: itemCompont
            anchors.top: parent.top
            anchors.topMargin: 10
            width: mainRect.width
            height: 50

            function onDisDeleteThis() {
                loader1.sourceComponent = undefined
            }

            onLoaded: {
                item.color = 'red'
                loader1.item.deleteThis.connect(loader1.onDisDeleteThis)
            }
        }

        Loader {
            id: loader2
            source: 'qrc:/QML/TestCompont.qml'
            anchors.top: loader1.bottom
            anchors.topMargin: 10
            width: mainRect.width
            height: 50

            function onDisDeleteThis() {
                loader2.source = ''
            }

            onLoaded: {
                loader2.item.deleteThis.connect(loader2.onDisDeleteThis)
            }
        }

        Component {
            id: itemCompont
            Rectangle {
                id: compontRect
                color: 'blue'
                implicitWidth: 200
                implicitHeight: 50

                signal deleteThis()

                Text {
                    id: interText
                    anchors.left: parent.left
                    anchors.leftMargin: 10
                    anchors.verticalCenter: parent.verticalCenter
                    text: qsTr("text")
                }
                Button {
                    anchors.margins: 5
                    anchors.top: parent.top
                    anchors.bottom: parent.bottom
                    anchors.right: parent.right
                    text: '刪除'

                    onClicked: {
                        compontRect.deleteThis()
                    }
                }
            }
        }
    }
}

4. 使用JavaScript中的語句載入/刪除元件

QML支援使用JavaScript動態建立/銷燬物件,有兩種方式動態建立物件:

  • 使用Qt.createComponent()動態建立一個元件物件,然後使用ComponentcreateObject()方法建立物件。
  • 使用Qt.createQmlObject()從一個QML字串直接建立一個物件。

如果QML檔案中嵌入Component,可以直接使用這個元件的createObject()方法建立元件;使用Component的destroy()方法刪除已經建立的元件。destroy()方法可以指定一個延時,不過不指定,他會在適當的時候刪除。
下面是一個簡單的示例:

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4

Window {
    width: 800
    height: 600
    visible: true

    Rectangle {
        id: mainRect
        anchors.fill: parent
        property var mainRectComponent: null

        Column {
            id: mainColumn
            spacing: 5

            width: parent.width
            property var count: 0

            function deleteItems(object) {
                object.destroy()
            }

            function createItem() {
                var color = 'red'
                if (mainColumn.count % 3 === 1)
                    color = 'yellow'
                else if (mainColumn.count % 3 === 2)
                    color = 'blue'
                mainColumn.count++

                // 建立一個元件
                var obj = itemCompont.createObject(mainColumn, {"color": color, "width": mainRect.width})
                //obj.setCurentObject(obj)
                obj.setCurrentText('Component' + mainColumn.count.toString())
                obj.deleteThis.connect(mainColumn.deleteItems)

                // 建立檔案中的元件
                var obj2 = mainRect.mainRectComponent.createObject(mainColumn,
                                                        {'color': Qt.rgba(0.4, 0.8, 0.6, 1.0)
                                                        ,'width': mainRect.width})
                obj2.setCurrentText('Component' + mainColumn.count.toString() + ', From File TestComponent')
                obj2.deleteThis.connect(mainColumn.deleteItems)
            }
        }

        Button {
            anchors.top: mainColumn.bottom
            anchors.topMargin: 10
            anchors.right: mainRect.right
            anchors.rightMargin: 10
            text: '新增'

            onClicked: {
                mainColumn.createItem()
            }
        }

        Component.onCompleted: {
            if (mainRectComponent == null)
                mainRectComponent = mainRectComponent = Qt.createComponent('qrc:/QML/TestCompont.qml')
        }

        Component {
            id: itemCompont
            Rectangle {
                id: compontRect
                color: 'blue'
                implicitWidth: 200
                implicitHeight: 50
                property var currentObject: ''

                signal deleteThis(var obj)

                // 設定文字的內容
                function setCurrentText(textName) {
                    interText.text = textName
                }

                Text {
                    id: interText
                    anchors.left: parent.left
                    anchors.leftMargin: 10
                    anchors.verticalCenter: parent.verticalCenter
                    text: qsTr("text")
                }
                Button {
                    anchors.margins: 5
                    anchors.top: parent.top
                    anchors.bottom: parent.bottom
                    anchors.right: parent.right
                    text: '刪除'

                    onClicked: {
                        compontRect.deleteThis(compontRect)
                    }
                }

                Component.onCompleted: {
                    compontRect.currentObject = parent
                }
            }
        }
    }
}

Component.createObject()的方法,第一個引數指定它的父物件,第二個引數可以指定這個元件的一些引數。
程式碼的顯示效果如下:
JavaScript動態建立和刪除