1. 程式人生 > >Qt Quick 事件處理之訊號與槽

Qt Quick 事件處理之訊號與槽

    前面兩篇文章《QML 語言基礎》和《Qt Quick 簡單教程》中我們介紹了 QML 語言的基本語法和 Qt Quick 的常見元素,親們,通過這兩篇文章,您應該已經可以完成簡單的 Qt Quick 應用了。接下來呢,哈,我們要介紹 Qt Quick 中一個灰常灰常重要的主題:事件處理。這將是比較長長長長的一篇,哦,不還有後續好幾篇……廢話少說,還是談正事兒吧兄弟姐妹們。

    本文是作者 Qt Quick 系列文章中的一篇,其它文章在這裡:

    GUI 應用都是基於事件的(同學,這麼說對嗎?),不管是用 C++ 還是用 QML ,你的應用都要處理事件,否則的話,哼哼,要你好看!當然當然,你也可以什麼事兒不幹,就搭個靜態介面放那裡欣賞……

    Qt Quick 最大的一個特點,是與 Qt 元物件系統的結合;而這裡邊,我們熟稔的,鼎鼎大名大名鼎鼎的,要不斷打交道的,就是訊號與槽了。歷史是割不斷的,繼承與發展才是正確的價值觀……,瞭解過 Qt 的開發者一定對訊號與槽印象深刻。在 QML 中,在 Qt Quick 中,要想妥善的處理各種事件,同樣離不開訊號與槽。所以呢,在介紹具體的事件之前,我們先要介紹 QML 中如何使用訊號與槽。

    為了演示本文的示例,我們先介紹一個工具: qmlscene 。

qmlscene 工具

    這是 Qt 框架提供的便利工具,使用它,你可以不用建立專案不用撰寫 C++ 程式碼,就可以看到你編寫的 qml 檔案的效果。我們以 Windows 7 系統為例, qmlscene 需要在命令列視窗中使用。你可以這樣開啟 Qt 自帶的命令列開發環境,參考圖 1 找到命令列環境的快捷方式:


            圖 1 Qt 命令列環境的快捷方式

    一旦你打開了命令列工具,它會幫你設定好 Qt 需要的環境變數,敲一個 qmake 命令試試吧。如和 圖 2 所示:


            圖 2 Qt 命令列開發環境

    如果你想知道 qmlscene 工具的詳細用法,請輸入 qmlscene --help 命令。如圖 3 :


            圖 3  qmlscene 的幫助

    現在,使用 cd 命令切換到你存放 qml 文件的目錄下,就可以驗證 qml 的效果了。只需要執行這樣的命令: qmlscene yourapp.qml 。當然,yourapp.qml 要替換為你實際的 qml 文件的名字。我這裡只是示例。如果你直接輸入 qmlscene 命令來執行,那麼它會開啟一個檔案選擇對話方塊,讓你選擇一個 qml 文件,當你選擇了之後呢,該文件對應的介面就會顯示出來。我建議你使用 qmlscene yourapp.qml 這種方式,無它,唯快爾。

    來看一個簡單的 Hello World ,qml 文件是 hello_world.qml ,內容如下:

import QtQuick 2.0
import QtQuick.Controls 1.1

Rectangle {
    width: 320;
    height: 240;
    color: "gray";
    
    Text {
        anchors.centerIn: parent;
        text: "Hello World!";
        color: "blue";
        font.pixelSize: 32;
    }
}

    在命令列環境執行 qmlscene hello_world.qml ,效果如圖 4 所示:


            圖 4 使用 qmlscene 執行 Hello World 示例

    好啦, qmlscene 的介紹到此為止,下面我們來看訊號與槽了。

連線 QML 型別的已知訊號

    我們先看一個簡單的示例, qml 中只有一個退出按鈕,點選退出應用。 qml 文件為 button_quit.qml ,內容如下:

import QtQuick 2.0
import QtQuick.Controls 1.1

Rectangle {
    width: 320;
    height: 240;
    color: "gray";
    
    Button {
        text: "Quit";
        anchors.centerIn: parent;
        onClicked: {
            Qt.quit();
        }
    }
}

    使用 qmlscene 執行 button_quit.qml 效果如圖 5 所示:


            圖 5 button_quit 示例效果

onClicked:{} 

    對,就是這個 onClicked ,其實就包含了 QML  中使用訊號與槽的一般形式:訊號處理器。

訊號處理器

    訊號處理器,其實等價於 Qt 中的槽。但是我們沒有看到類似 C++ 中的明確定義的函式……沒錯,就是這樣,你的的確確只看到了一對花括號!對啦,這是 JavaScript 中的程式碼塊。其實呢,你可以理解為它是一個匿名函式。而 JavaScript 中的函式,其實具名的程式碼塊。函式的好處是你可以在其它地方根據名字呼叫它,而程式碼塊的好處是,除了定義它的地方,沒人能呼叫它,一句話,它是私有的。程式碼塊就是一系列語句的組合,它的作用就是使語句序列一起執行。

    讓我們回頭再看訊號處理器,它的名字還有點兒特別,一般是 on{Signal} 這種形式。在上節的示例中, Button 元素有一個名為 clicked() 的訊號,我們提供的訊號處理器是醬紫的:

        onClicked: {
            Qt.quit();
        }

    非常簡單吧,僅僅是呼叫 Qt.quit() 來退出應用而已。

    Qt 物件是 Qt Quick 匯出到 QML 環境中的物件,它的 quit() 方法退出應用。還有很多其它的方法,比如 rgba() 用於構造一個顏色(color型別), md5() 用來計算一段資料的 MD5 值……

    你看到了,當訊號是 clicked() 時,訊號處理器就命名為 onClicked 。就這麼簡單,以 on 起始後跟訊號名字(第一個字母大寫)。如果你點選我們的 quit 按鈕,應用就真的退出了。

    上面的示例,訊號處理器放在擁有訊號的元素內部,當元素訊號發射時處理器被呼叫。還有一種情況,要處理的訊號不是當前元素髮出來的,而是來自其它型別(物件)比如處理按鍵的 Keys ,這就是附加訊號處理器。

附加訊號處理器

    在 QML 語言的語法中,有一個附加屬性(attached properties)和附加訊號處理器(attached signal handlers)的概念,這是附加到一個物件上的額外的屬性。從本質上講,這些屬性是由附加型別(attaching type)來實現和提供的,它們可能被附加到另一種型別的物件上。附加屬性與普通屬性的區別在於,物件的普通屬性是由物件本身或其基類(或沿繼承層級向上追溯的祖先們)提供的。

   舉個例子,下面的 Item 物件使用了附加屬性和附加訊號處理器:

import QtQuick 2.0

Item {
    width: 100; 
    height: 100;

    focus: true;
    Keys.enabled: false;
    Keys.onReturnPressed: console.log("Return key was pressed");
}

    你看, Item 物件可以訪問和設定 Keys.enabled 和 Keys.onReturnPressed 的值。

    enabled 是 Keys 物件的一個屬性。 

    onReturnPressed 其實是 Keys 物件的一個訊號。

    對於附加訊號處理器,和前面講到的普通訊號處理器又有所不同。普通訊號處理器,你先要知道訊號名字,然後按照 on{Signal} 的語法來定義訊號處理器的名字;而附加訊號處理器,訊號名字本身已經是 onXXX 的形式,你只要通過附加型別名字引用它,把程式碼塊賦值給它即可。下面是另外的程式碼片段:

Rectangle {
    width: 320;
    height: 480;
    color: "gray";
    
    focus: true;
    Keys.enabled: true;
    Keys.onEscapePressed: {
        Qt.quit();
    }
}

    這個程式碼片段實現的功能非常簡單:使用者按下 Esc 鍵時退出應用。

    Component 物件也有一些附加訊號,如 Component.onCompleted() 、 Component.onDestruction() 。可以用來在 Component 建立完成或銷燬時執行一些 JavaScript 程式碼來做與初始化或反初始化相關的工作。比如下面的程式碼:

Rectangle {
    Component.onCompleted: console.log("Completed Running!");
    Component.onDestruction: console.log("Destruction Beginning!");
}

    訊號處理器與附加訊號處理器有一個共性:響應訊號的程式碼都放在元素內部,通過 JavaScript 程式碼塊就地實現。而其實呢, Qt Quick 中還有另外一種方式來處理訊號與槽,那就是:專業的 Connections 。

Connections

    一個 Connections 物件建立一個到 QML 訊號的連線。

    前面兩節在處理 QML 訊號時,都是用 on{Signal} 這種就地程式碼塊的方式。而在有些情況下,這樣的處理並不方便。比如:

  • 你需要將多個物件連線到同一個 QML 訊號上
  • 你需要在發出訊號的物件的作用域之外來建立連線
  • 發射訊號的物件沒有在 QML 中定義(可能是通過 C++ 匯出的,這很常見)

    Connections 有一個屬性名為 target ,它呢,指向發出訊號的物件。

    下面就看看 Connections 怎麼使用。一般的用法:

Connections {
    target: area;
    on{Signal}: function or code block;
}

   來看一個實際的示例,是醬紫的:介面上放置兩個文字,一個按鈕,每點按鈕一次,兩個文字物件都變顏色,而它們的顏色隨機的。下面是示例程式碼:
import QtQuick 2.0
import QtQuick.Controls 1.1

Rectangle {
    width: 320;
    height: 240;
    color: "gray";
    
    Text {
        id: text1;
        anchors.horizontalCenter: parent.horizontalCenter;
        anchors.top: parent.top;
        anchors.topMargin: 20;
        text: "Text One";
        color: "blue";
        font.pixelSize: 28;
    }
    
    Text {
        id: text2;
        anchors.horizontalCenter: parent.horizontalCenter;
        anchors.top: text1.bottom;
        anchors.topMargin: 8;
        text: "Text Two";
        color: "blue";
        font.pixelSize: 28;
    }
    
    Button {
        id: changeButton;
        anchors.top: text2.bottom;
        anchors.topMargin: 8;
        anchors.horizontalCenter: parent.horizontalCenter;
        text: "Change";
    }
    
    Connections {
        target: changeButton;
        onClicked: {
            text1.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
            text2.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

    程式碼比較簡單,除了 Connections 和 Math ,沒有其它的新內容,都是 《Qt Quick 簡單教程》和《QML 語言基礎》中講過的。我在 Connections 物件中指定 target 為 changeButton (Change按鈕的 id),然後定義了 onClicked 訊號處理器,在訊號處理器中使用 Math 物件的 random() 方法構造顏色值來改變兩個文字的顏色。

    Math 是 JavaScript 語言內建的物件,有 random() / sin() / max() / min() / abs() 等等方法,參見 w3c 的文件

    圖 6 是執行後的效果圖:


            圖 6 Connections 的使用

    到現在為止,我們說的都是如何使用 QML 中已有型別定義的訊號。這些訊號呢,其實又分類兩類。一類是由使用者輸入產生的,比如按鍵、滑鼠、觸控式螢幕、感測器等,另一類呢是由物件狀態或屬性變化產生的,比如 Image 物件的 status 屬性(在《Qt Quick 簡單教程》有用到)。那麼有一個問題,就是,怎樣知道一個物件有哪些訊號?

如何尋找感興趣的訊號

    怎樣找到你感興趣的訊號呢?

Qt 幫助

    首先是查閱 Qt 幫助,你可以使用 Qt 幫助的索引模式,以你關心的物件名字為關鍵字檢索,比如 Button ,檢索結果如圖 7 所示:


            圖7 使用 Qt 幫助索引模式檢索 Button 物件

    有時你會在查詢結果中看到多個連線,點進去看看是否是 QML 型別即可。

    還有另外一種方式,使用 Qt 幫助的目錄模式。如圖 8 所示:


            圖 8 使用 Qt 幫助目錄模式

    一旦你找到一個物件的文件,你可以找到它的部分訊號說明。還是以 Button 為例,看圖 9:


            圖 9 Button 的訊號 clicked()

    Qt Quick  相關型別的文件中,你可以看到物件的屬性和訊號。列為屬性的,可以在 QML 中訪問;列為訊號的,可以連線它,通過訊號處理器來響應用於操作。

    至於具體某個屬性或訊號是何含義,點選它們,跟過去看看吧。

    話說,Qt 的文件是否列出了 Qt Quick 型別的所有訊號了呢?想必我這麼說你用腳趾頭也可以想到答案:沒有!個人認為這是 Qt 5.2 文件關於 Qt Quick 和 QML 型別手冊的一個缺失。前面提到 QML 中的訊號,一類是輸入事件觸發的,一類是屬性變化觸發的。文件中缺失的,正是屬性變化觸發的那些訊號。不過呢,不過我們有辦法找到它。

從 Qt Quick 標頭檔案檢視屬性相關的訊號

    要說呢, Qt Quick 中你看到的很多物件,都是 Qt C++ 中實現,然後匯入到 QML 環境中的。所以呢,如果你關心那些被文件隱藏了的訊號,可以這麼做:

  1. 找到 QML 型別對應的 C++ 型別
  2. 找到 C++ 型別的標頭檔案,檢視屬性宣告來確認是否有訊號與屬性關聯

    怎麼找 QML 型別對應的 C++ 型別呢?很簡單,只需要使用 Component.onCompleted 附加訊號,在附加訊號處理器中輸出型別資訊即可。示例程式碼:

import QtQuick 2.0
import QtQuick.Controls 1.1

Rectangle {
    width: 320;
    height: 240;
    color: "gray";
    
    Text {
        id: text1;
        anchors.centerIn: parent;
        text: "Hello World!";
        color: "blue";
        font.pixelSize: 32;
    }
    
    Button {
        id: button1;
        text: "A Button";
        anchors.top: text1.bottom;
        anchors.topMargin: 4;
    }
    
    Image {
        id: image1;
    }
    
    Component.onCompleted: {
        console.log("QML Text\'s C++ type - ", text1);
        console.log("QML Button\'s C++ type - ", button1);
        console.log("QML Image\'s C++ type - ", image1);
    }
}

    如程式碼所示,我們使用 console 物件來輸出 QML 物件,它會打印出 QML 物件的實際型別。圖 10 是使用 qmlscene 執行 cplusplus_types.qml 的效果圖:


             圖 10 列印 QML 型別對應的 C++ 型別

    別看介面效果哦,注意看命令列視窗的輸出。對,QML Text 對應的 C++ 型別是 QQuickText , QML Image 對應的 C++ 型別是 QQuickImage ,而 Button ,其實是 QML 中定義的物件(含有 QMLTYPE 字樣)。我這裡使用的 Qt 5.2.0 ,如果是其他的 Qt 版本,比如 Qt 4.7 / Qt 4.8 ,能不能看到我就不知道了。

    下面我們就以 QQuickText 為例,找到它的標頭檔案,路徑是 C:\Qt\Qt5.2.0\5.2.0\mingw48_32\include\QtQuick\5.2.0\QtQuick\private\qquicktext_p.h 。你的環境中根據 Qt SDK 安裝目錄,路徑可能有所不同。

    看看 QQuickText 類的宣告吧(我截取了屬性部分的幾行程式碼):

// qquicktext_p.h
//
class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
{
    Q_OBJECT
    Q_ENUMS(HAlignment)
    Q_ENUMS(VAlignment)
    Q_ENUMS(TextStyle)
    Q_ENUMS(TextFormat)
    Q_ENUMS(TextElideMode)
    Q_ENUMS(WrapMode)
    Q_ENUMS(LineHeightMode)
    Q_ENUMS(FontSizeMode)
    Q_ENUMS(RenderType)

    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
    Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
    Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
    Q_PROPERTY(QColor linkColor READ linkColor WRITE setLinkColor NOTIFY linkColorChanged)
    Q_PROPERTY(TextStyle style READ style WRITE setStyle NOTIFY styleChanged)
    ...
}

    親愛的,看到了嗎,那麼多的 Q_PROPERTY 巨集啊。  Q_PROPERTY 巨集就是用來定義 QML 中可訪問屬性的,當你看到 NOTIFY 字樣,它後面的欄位就是與屬性繫結的訊號的名字。 Qt 實現了動態屬性繫結,當你為 QML Text 的屬性 color 賦值時,實際上會呼叫到 QQuickText 的 setColor() 函式,也會觸發 colorChanged() 訊號。

    再來看看 text 和 color 對應的訊號原型:

class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
{
    Q_OBJECT
    ...
Q_SIGNALS:
    void textChanged(const QString &text);
    void colorChanged();   
}

    看到了吧, textChanged 訊號有個 text 引數。我們來看看 textChanged 訊號怎樣在 QML 中使用。示例程式碼(property_signal.qml):
import QtQuick 2.0
import QtQuick.Controls 1.1

Rectangle {
    width: 320;
    height: 240;
    color: "gray";
    
    Text {
        id: hello;
        anchors.centerIn: parent;
        text: "Hello World!";
        color: "blue";
        font.pixelSize: 32;
        onTextChanged: {
            console.log(text);
        }
    }
    
    Button {
        anchors.top: hello.bottom;
        anchors.topMargin: 8;
        anchors.horizontalCenter: parent.horizontalCenter;
        text: "Change";
        onClicked: {
            hello.text = "Hello Qt Quick";
        }
    }
}

    當用戶點選按鈕時,改變 Text 物件的文字為 "Hello Qt Quick" 。而我在 Text 物件中實現了 onTextChanged 訊號處理器,使用 console.log 輸出新的文字。

    注意啦,QML 訊號的引數名字,可以直接在訊號處理器中訪問。之前只用沒說,這裡特意說一下這點。如果你通過標頭檔案找屬性繫結的訊號,就可以觀察訊號的引數,在 QML 中使用。

    圖 11 是執行效果:


            圖 11 屬性繫結的訊號

    你看,圖片上的文字變了哈,命令列也輸出了新的文字:"Hello Qt Quick" 。喏,沒騙你。

    行文至此,如何在 QML 中使用已知型別的訊號,已經介紹差不多了。

定義自己的訊號

    當自定義型別不可避免,當你需要通知別的物件你的狀態發生了變化,當你物件的粉絲想了解你物件的近況……此時此刻,彼時彼刻,最好的方法, Qt 給我們的,QML 給我們的,還是訊號。

    現在我們就來看怎麼定義自己的訊號。

自定義訊號與使用

    如果你自己定義新的 QML 型別,可以使用 signal 關鍵字給你的型別新增訊號。其語法如下:

signal <name>[([<type> <parameter name>[, ...]])]

    這是你的型別通告自己狀態的最好的方式,符合 Qt 的風格,作為使用 Qt 的開發人員,還是崇德向善吧。

    訊號其實是個方法(函式),所以呢,它的發射,實際是通過呼叫以訊號名為名的方法達成的。

    舉個例項的例子:我們在介面上放一個字串,兩個代表顏色的小方塊,點小方塊,字串的顏色就變成小方塊的顏色。先看程式碼(my_signal.qml):

import QtQuick 2.0
import QtQuick.Controls 1.1

Rectangle {
    width: 320;
    height: 240;
    color: "#C0C0C0";
    
    Text {
        id: coloredText;
        anchors.horizontalCenter: parent.horizontalCenter;
        anchors.top: parent.top;
        anchors.topMargin: 4;
        text: "Hello World!";
        font.pixelSize: 32;
    }
    
    Component {
        id: colorComponent;
        Rectangle {
            id: colorPicker;
            width: 50;
            height: 30;
            signal colorPicked(color clr);
            MouseArea {
                anchors.fill: parent
                onPressed: colorPicker.colorPicked(colorPicker.color);
            }
        }
    }
    
    Loader{
        id: redLoader;
        anchors.left: parent.left;
        anchors.leftMargin: 4;
        anchors.bottom: parent.bottom;
        anchors.bottomMargin: 4;
        sourceComponent: colorComponent;
        onLoaded:{
            item.color = "red";
        }
    }
    
    Loader{
        id: blueLoader;
        anchors.left: redLoader.right;
        anchors.leftMargin: 4;
        anchors.bottom: parent.bottom;
        anchors.bottomMargin: 4;
        sourceComponent: colorComponent;
        onLoaded:{
            item.color = "blue";
        }
    }
    
    Connections {
        target: redLoader.item;
        onColorPicked:{
            coloredText.color = clr;
        }
    }
    
    Connections {
        target: blueLoader.item;
        onColorPicked:{
            coloredText.color = clr;
        }
    }
}

    這次程式碼稍微有點長了。現在我來充當導遊,請跟緊我哦,別擔心,不會強制你們買東西的。

    首先定義了一個 Text 物件,id 為 coloredText ,後面會根據這個 id 來改變它的顏色。

    然後我定義了一個元件,元件內有一個 Rectangle 物件,這裡是我們定義訊號的地方。我設定 Rectangle 的尺寸,然後定義了訊號 colorPicked ,語句如下:

signal colorPicked(color clr);
    為了觸發訊號,我給 Rectangle 引入了 MouseArea 。MouseArea 是專門處理滑鼠操作的 item ,這裡我們先知道它有一個 onClicked() 訊號就行了。我們給這個訊號指定訊號處理器,在訊號處理器中呼叫我們剛定義的訊號:colorPicker.colorPicked(colorPicker.color); ……如你所見,訊號的觸發就是一個函式呼叫。
    元件是可以重複利用的,一個元件可以在一個單獨的 qml 檔案中定義,也可以嵌入到其它 qml 文件中來定義以方便簡單元件的使用。這裡我選擇在主 qml 文件內嵌入元件的定義。定義好了元件,就可以使用 Loader 來載入元件了。

    Loader 是專門用來動態建立元件的,它可以從 qml 檔案中建立元件,也可以指定 sourceComponent 來建立,這裡的示例,因為元件是嵌入在主 qml 檔案中定義的,所以使用了 sourceComponent 方式。我給每個 Loader 一個 id ,以便後面連線時使用。我還使用 anchors 為 Loader 佈局。最後呢,在 Loader 的 onLoaded 訊號處理器內給 Rectangle 物件配置顏色。

    建立完 Loader ,就是建立連線了。這裡使用 Connections 來建立訊號的連線,target 指向剛才說的 Loader 物件的 item 屬性, item 屬性實際指向 Loader 建立的物件。在 Connections 物件中,通過 onColorPicked 訊號處理器響應使用者點選操作。你看到了,我們定義 colorPicked 訊號時命名的引數是 clr ,所以 Connections 的訊號處理器中可以直接使用它給 coloredText 物件複製。

    好了,看看初始執行的效果,圖 12 :


            圖 12 自定義訊號之變色文字初始效果圖

    圖 13 是我點選了紅色的顏色選擇元件時的效果:


            圖 13 選擇紅色後的效果

    嗯,不知道你是否已經明白如何使用自定義訊號?多練練吧。這個示例用到的 Component 和 Loader ,還請您先自行查閱 Qt 幫助來理解,後續我們有專門的文章來講述它們。

連線訊號與槽

    前面我們使用訊號時,要麼通過訊號處理器,要麼使用 Connections 物件。其實在 QML 中還有一種更一般的方式。先回想下 Qt C++ 中我們如何使用訊號與槽…… QObject::connection() ,諾,木錯,就是它了。對應的,在 QML 中,其實 signal 是個物件,它也有一個 connect() 方法,你可以使用它連線到任意的方法上哦。有 connect() 就有 disconnect() ,正確, signal 物件的的確確有這兩個方法,允許我們使用它維護連線。

    signal 物件的 connect() 方法允許你連線一個訊號到另外一個訊號或者方法。其實沒差別,訊號本身也是個方法(函式)。當訊號發射時,連線到訊號上的其它訊號或方法就會被呼叫。

    signal 物件的這種連線方式,使用起來比訊號處理器更加靈活。前面介紹訊號處理器時,已經提到,訊號處理器和訊號是一對一的關係。而 signal 物件的這種連線方式,使得一個訊號能夠連線多個方法。

    舉個簡單的例子來看看如何使用吧。下面的程式碼(來自 Qt 幫助), messageReceived 訊號通過 connect() 方法連線到了三個方法上。

Rectangle {
    id: relay;

    signal messageReceived(string person, string notice);

    Component.onCompleted: {
        relay.messageReceived.connect(sendToPost);
        relay.messageReceived.connect(sendToTelegraph);
        relay.messageReceived.connect(sendToEmail);
        relay.messageReceived("Tom", "Happy Birthday");
    }

    function sendToPost(person, notice) {
        console.log("Sending to post: " + person + ", " + notice);
    }
    function sendToTelegraph(person, notice) {
        console.log("Sending to telegraph: " + person + ", " + notice);
    }
    function sendToEmail(person, notice) {
        console.log("Sending to email: " + person + ", " + notice);
    }
}

    上面是訊號連線方法的示例,實際上訊號也可以連線訊號。我們說了,訊號本質是一個方法(函式),所以,訊號連線訊號等同於訊號連線方法。下面是一個簡單的示例:
Rectangle {
    id: forwarder;
    width: 100; 
    height: 100;

    signal send();
    onSend: console.log("Send clicked");

    MouseArea {
        id: mousearea;
        anchors.fill: parent;
        onClicked: console.log("MouseArea clicked");
    }

    Component.onCompleted: {
        mousearea.clicked.connect(send);
    }
}

    這裡我們給 Rectangle 定義了一個訊號 send() ,在 Component.onCompleted 附加訊號處理器中,把 MouseArea 物件的 clicked 訊號連線到 Rectangle 的 send() 訊號上。

    K.O. !終於把 QML 中的訊號與槽介紹完了。

    溫故知新哦,回顧一下本系列的文章:Qt Quick 簡介

下一次,我們將學習如何在 Qt Quick 中處理常見的事件,包括按鍵、滑鼠、定時器等。敬請關注。