8.QML中的元件Component
阿新 • • 發佈:2019-02-11
本篇文章介紹一下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物件。
- 當source或sourceComponent屬性發生變化時,它之前的物件會被銷燬,新物件會被載入。
- 當source設定為空串,或者sourceComponent設定為undefined,將會銷燬當前物件,相關資源也會被釋放,Loader物件會變成一個空物件。
- item屬性指向他載入的元件的頂層Item,比如上面的示例item就為Rectangle。
下面是一個使用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()動態建立一個元件物件,然後使用Component的createObject()方法建立物件。
- 使用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()的方法,第一個引數指定它的父物件,第二個引數可以指定這個元件的一些引數。
程式碼的顯示效果如下: