QML中的信號和函數
https://blog.csdn.net/iEearth/article/details/41801333
在Qt C++中,signals & slots是其核心機制,是應用程序與UI組件交互的神經網絡,同樣在QML中,也有類似的signal & handler機制,signal信號就是我們常說的一種事件,可通過signal handler信號處理器來處理這個信號。當某個signal信號被發送時,對應的handler信號處理器也被觸發,我們就可以在handler信號處理器中做一些事情,來處理這個signal信號事件。
1、“HelloWorld”信號簡述
下面是一個簡單的例子:
import QtQuick 2.3
import QtQuick.Controls 1.2
Rectangle {
width: 360; height: 200
color: "lightblue"
Button {
text: "Quit!"
anchors.centerIn: parent
onClicked: Qt.quit()
}
}
在一個Rectangle中有一個Button,這個Button默認有一個clicked()信號,相應的就會有一個onClicked信號處理器。如果有一個signal()信號,那么相應的信號處理器handler就是onSignal,注意大小寫,信號中有參數時信號處理器會接收到且可以使用。當我們用鼠標左鍵點擊例子中的的Button時,就會發送clicked()信號,觸發信號處理器onClicked,這里調用了Qt.quit()函數來退出應用程序。
2、屬性handler
當QML屬性值改變時,會自動發送一個該屬性值變化的信號,對應的信號處理器的格式是on<Property>Changed,不管是QML內建的屬性,還是我們自定義的屬性,一旦屬性值改變,都會觸發相應的信號處理器,舉例如下:
import QtQuick 2.3
import QtQuick.Controls 1.2
Rectangle {
width: 360; height: 100
color: "lightblue"
onColorChanged: console.log("color changed")
Button {
text: "Change Color"
anchors.centerIn: parent
onClicked: parent.color = "yellow"
}
}
點擊Button按鈕時,Rectangle的color會從原來的lightblue變為yellow,這時就會觸發onColorChanged,輸出“color changed”。
3、附加signalhandler
附加信號處理器接收的信號來自附加元素類型,而不是當前對象,例如下面例子中的Keys和Component:
import QtQuick 2.3
Rectangle {
id: rect
width: 360; height: 100
focus: true
Keys.onSpacePressed: rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
Component.onCompleted: rect.color = "green"
}
上述例子中我們使用了Component.onCompleted,在組件完成時設置Rectangle的顏色為綠色,還使用了Keys.onSpacePressed,按下空格鍵時隨機改變Rectangle的顏色。Math是JavaScript的對象,在這里我們可以直接使用,因為QML是對JavaScript的一種擴展,支持JavaScript的大部分東西。
4、使用Connections連接handler
在前面的例子中,我們對某個信號signal,直接在當前對象下使用了on<Signal>形式的信號處理器,但是在某些情況下,我們不得不使用Connections來連接一個信號,比如說,多個對象連接到同一個信號時,在發射信號的對象作用域之外建立連接時,連接不是QML定義的對象(如在C++中定義的對象)時,舉例說明:
import QtQuick 2.3
Item {
width: 500; height: 150
Row {
spacing: 50
Rectangle {
width: 100; height:100
color: "red"
MouseArea {
anchors.fill: parent
onClicked: parent.color=
Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
}
Rectangle {
id: rectYellow
width: 100; height:100
color: "yellow"
MouseArea {
anchors.fill: parent
Connections {
onClicked: rectYellow.color=
Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
}
}
Rectangle {
id: rectGreen
width: 100; height:100
color: "green"
MouseArea {
id: mouseArea
anchors.fill: parent
}
Connections {
target: mouseArea
onClicked: rectGreen.color=
Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
}
}
}
上述例子,列舉了三種用法。第一種、第二種用法類似,都是直接在MouseArea作用域內連接,可以看出第二種方法的Connections可以省略,MouseArea指定了一塊區域來處理鼠標事件,第三種方法是在MouseArea作用域之外建立連接,也就不得不用Connections,三種方法都是在鼠標點擊時隨機改變Rectangle的顏色。
5、自定義信號、函數
在QML中,我們可以自定義信號和函數,首先需要聲明的是,不能像C++那樣支持重載,語法如下:
signal <signalName>[([<type> <parameter name>[, …]])]
function <functionName>([<parameterName>[, ...]]) { <body> }
自定義的信號和函數都可以帶參數,不同的是,信號要指明參數類型,而函數卻用不着,這是為什么呢,因為函數的參數類型默認為萬能的var類型,而且也沒有像C++那樣必須指明返回值類型,下面是一個綜合的例子:
import QtQuick 2.3
Item {
width: 600; height: 100
Rectangle {
id: rect1
width: 100; height: 100
color: "lightblue"
Text {
id: text1
anchors.centerIn: parent
text: "custom \n signal"
}
}
Rectangle {
id: rect2
width: 100; height: 100
anchors.right: parent.right
color: "lightblue"
function changeColor(obj) {
obj.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
Text {
id: text2
anchors.centerIn: parent
text: "custom \n funtion"
}
}
Component {
id: colorComponent
Rectangle {
id: colorMaker
width: 100; height:100
signal colorMade(color col) // 信號
MouseArea {
anchors.fill: parent
onClicked: colorMaker.colorMade(colorMaker.color) // 調用信號函數, 類似於發射信號 colorMade
}
}
}
Loader {
id: redLoader
anchors.left: rect1.right
anchors.leftMargin: 50
sourceComponent: colorComponent
onLoaded: item.color = "red"
}
Loader {
id: greenLoader
anchors.right: rect2.left
anchors.rightMargin: 50
sourceComponent: colorComponent
onLoaded: item.color = "green"
}
Connections { // 將目標對象信號與槽函數進行連接
target: redLoader.item
onColorMade: { // 處理目標對象信號的槽函數
rect2.changeColor(text2) //
text1.color = col
}
}
Connections { // 將目標對象信號與槽函數進行連接
target: greenLoader.item
onColorMade: { // 處理目標對象信號的槽函數
rect2.changeColor(text2)
text1.color = col
}
}
}
這段代碼綜合了許多知識點,貌似有點復雜,我們且看且分析。在rect2中自定義了一個函數changeColor(obj),目的是隨機改變obj的顏色,函數參數沒有顯式地指明其類型,是個動態類型。Component定義了一個組件,這里我們自定義的信號是colorMade(color col),信號的參數類型是要明確指明的,信號處理器可以使用這個參數,在C++中使用emit關鍵字發送一個信號,在QML中信號就是個特殊的函數,可以像函數那樣來使用。Loader動態加載一個組件,其item屬性保存的就是加載的那個組件,然后用Connections來連接我們自定義的信號,在信號處理器中又調用了我們自定義的函數。
6、使用connect() / disconnect()
再介紹一個連接信號的方法,信號本身有connect() / disconnect()兩個函數來連接或斷開一個信號或方法,不多說了,直接看代碼:
import QtQuick 2.3
Item {
id: item
signal employer(string name)
signal employee(string name)
// employee 的槽函數
onEmployee: console.log(name,“from signal”)
function employ(name) {
console.log(name,“from function”)
}
Component.onCompleted: {
// employer 信號 連接 多個槽函數或信號
item.employer.connect(employ)
item.employer.connect(employee)
employer("Bible")
}
}
例子中用信號分別連接了另外一個信號和函數,比較簡單,不再介紹了。
============== End
