[Qt QML] 如何在QML裡存取C++物件的類別成員
在之前的文章我們介紹了在QML如何呼叫C++的class function,那如果我們要直接存取類別成員時,該怎麼做呢?當然我們可以直接透過呼叫class function去做到這件事,但是如果該成員變數的值有所變動時,而這個值是我們需要在UI即時呈現變化的,那該如何處理呢?簡單來說,就是再結合上一篇所介紹的,在QML裡建立與C++物件的connections,當該變數的值有所改變時,發出一個signal,其連接的slot function再去做對應的動作。但以實作上來看,可以有較簡潔的寫法,從程式碼上看不到有任何地方建立connections,但實際上概念就是透過connections去達成的,我們透過以下的簡單範例來解釋。
我們一樣先從畫面的解說和功能描述開始,如下圖,視窗中央有一段文字顯示目前count這個變數的值。另外有兩個Button,上方Button的功能是點擊後將count的值設定為3,而下方的則是將ㄙcount加10。一旦count的值改變,中央那段文字所看到的數字也會跟著改變。

Qt C++部分
我們一樣延續之前的程式碼進行修改,首先,在Controller這個class宣告一個private variable,其被賦予的值就是上面提到的count。
private:
int m_count{};
為了讓QML端可以方便存取這個variable,下面這一段是關鍵,主要是透過Q_PROPERTY這個macro定義欲存取的方式。
Q_PROPERTY(int count READ getCount WRITE setCount NOTIFY countChanged)
這一行的說明是,有一個名為count的property,它的data type是int,對於count這個property,提供了READ、WRITE、NOTIFY三個功能,而這三個功能分別對應的function就是getCount、setCount、countChanged。前面兩個應該容易理解,第三個其實就是一個signal,所以宣告如下。
signals:
void countChanged();
getCount()和setCount()這兩個function都很單純,就是對m_count的讀取和寫入,唯一要注意的就是在setCount()裡,當m_count值有所改變時,需要發送countChanged()這個signal,如此一來,QML端才能在不建立Connections的情況下,能收到該NOTIFY。
Qt QML部分
UI主要是顯示m_count的值,在前面C++的部分提到該變數在QML裡的存取設定,因為該變數屬於ctrl這個物件,變數名稱也已經透過設定時宣告為count,所以在QML裡對該變數的存取就是對於ctrl.count進行操作即可。以下面這段程式碼為例,就是將文字顯示(text)的部分,跟ctrl.count的值做一個Binding的動作。當C++物件(ctrl)的成員變數m_count(count)改變時(發出NOTIFY),就會獲取最新的值。如此一來,就不需要在QML建立Connections去做對應的動作。
Text {
id: txtCount
width: 100
height: 30
anchors.centerIn: parent
text: "Current count is " + ctrl.count
}
上面這一段顯示的是針對該變數的讀取(READ)部分,而寫入(WRTIE的部分),就直接assign值給該變數即可,這一部分就實作在當上方Button點擊時的動作。
onClicked: {
ctrl.count = 3;
}
身為從Qt Widget要轉換到QML開發的碼農, 您這幾篇篇幅雖短但是給我相當大的幫助, 非常感謝!
Whisley,謝謝你的回應。很高興能幫上忙,沒想到我的文章還是有人看得到,對我是鼓舞。如果有其他問題,也歡迎留言。或者私訊到我的臉書帳號,謝謝。