[Qt QML] 如何在QML裡建立與C++物件的connections

Spread the love

上一篇我們介紹了在QML中如何呼叫C++ class functions,這一篇我們講解一下,反過來如何從C++呼叫QML裡的JavaScript functions。不過這裡我要特別強調,實作上我們確實可以從C++這一層來呼叫QML裡的function,但實際上,以架構上的角度,並不建議如此設計。因為以架構上來說,UI這一層使用QML撰寫的程式碼只會有UI的相關邏輯,譬如說畫面流程的轉換,它不應該被屬於bussiness logic的C++這一層來操控。那應該怎麼做呢?最好是採用Qt裡的signal and slot機制來達到需要的結果,也就是說,以bussiness logic的角度,它只要在某事件發生時將signal發出即可,至於要接收該signal的物件就自行將connection建立起來,然後定義對應的動作(slot function)。

OK,既然在設計上不建議從C++呼叫QML裡的JavaScript functions,所以我覺得也沒有必要介紹該實作方式了。所以接下來就給一個簡單的範例程式,敘述如何在QML裡建立的與C++物件的connections。基於上一篇文章的範例程式,我們不修改畫面排版和組成元素,僅將按鈕上的文字修改如下圖,當按下按鈕時,經過三秒後觸發C++物件發送signal,用此來模擬bussiness logic的事件發生。

Qt C++部分

首先,我們延續上一篇文章的程式碼,在上一篇文章中我們定義了一個C++ class function名為quitApp()讓QML這一層呼叫,為了符合這裡定義的功能,我們將其改名為triggerEvent(),其實作的部分就是在seconds秒後發出signal,這裡將signal名稱定為eventTriggered()

void Controller::triggerEvent(int seconds)
{
    QTimer::singleShot(1000 * seconds, this, SIGNAL(eventTriggered()));
}

Qt QML部分

在QML建立connection就相對簡單,可以直接採用QML中的Connections元件,因為我們要建立的對象物件是C++裡的物件,在上一篇文章中我們就已經將該物件設定為QML裡的一個property,名為ctrl,所以這邊直接將target的值設為ctrl,表示連結的物件對象。

而slot function的部分比較特別,並不像在C++建立的時候,可以指定自定義的function,在QML裡有一個固定邏輯且方便的命名方式,就是固定為on<Signal>這個名稱,以這邊為例,signal名為eventTriggered,那對應的slot function就是onEventTriggered。規則就是signal的第一個字元必須是小寫英文字母,那slot function就是把第一個單字變大寫,然後前面加上“on”。

    Connections {
        target: ctrl

        onEventTriggered: {
            mainWindow.color = "red";
        }
    }

從上面程式碼可以看到,在slot function裡的實作,是將視窗底色改為紅色。不過這邊要注意的是,如果你使用的Qt版本是5.15以上,在QML這邊的語法有些改變,會在執行時出現以下這個錯誤訊息,但不影響執行結果。

QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }

從訊息中可以看到,原本之前的寫法已經不再使用了,雖然還是可以正常運行,不過建議還是依這訊息提示,將程式碼改為新的正確寫法,方法也很簡單,就是前面加個function就好。

    Connections {
        target: ctrl

        function onEventTriggered() {
            mainWindow.color = "red";
        }
    }

執行結果

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *