QML中的信號和函數


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

 


免責聲明!

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



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