qml的信號槽機制和qtwidget差不多,但是使用方法不一樣,qtwidget一般直接用connect函數把信號和槽一綁定就完事了,qml分為自動綁定和手動綁定。
信號自動綁定
在一個組件里面定義一個信號,用signal定義,當事件觸發,比如button的onclick,發送信號,連接信號槽,就是這個信號發出后對他進行一個處理,邊看例子邊講吧
//測試qml的信號槽機制
import QtQuick
import QtQuick.ControlsWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")//文本框Flickable {id: flickableanchors.centerIn: parentwidth: 200height: 200contentWidth: textEdit.widthcontentHeight: textEdit.heightclip: true
//滑動條部份,需要用flickable或者scrollbar包裝起來ScrollBar.vertical: ScrollBar {id: vbarwidth: 20policy: ScrollBar.AsNeededanchors {right: parent.righttop: parent.topbottom: parent.bottom}}TextEdit {id: textEditwidth: flickable.widthheight: Math.max(flickable.height, implicitHeight)wrapMode: TextEdit.Wrapcolor: "red"}}//測試信號按鈕Button{x:10y:10width: 40height: 20text: "btn1"signal haveClick()onClicked: {haveClick()}onHaveClick: {textEdit.append("btn1被點擊")}}}
上面這段代碼,我定義了一個文本框和一個按鈕,文本框有一個滑動條模塊,注意下,滑動條需要用scrollview或者flickable包裝一下,button中定義了一個信號haveclick(),當按鈕被點擊onclick的時候就會被觸發發送,發送出去自動綁定就是在信號名前面加上on并把信號名首字母大寫,后面跟上處理函數,如上onHaveClick: {textEdit.append("btn1被點擊")},textedit是我給文本框定義的id,我希望信號發出后,文本框能加上一行某某被點擊,上面的代碼可以直接復制到qml文件中區跑著看看,這個就是自動綁定信號槽。上面是信號槽綁定的一種方法,還有一種是類似JavaScript的箭頭函數或者c++的lamda函數表達式的。
信號槽的手動綁定
我們在發送者的內部定義信號,在接收者內部定義接收槽函數。信號發出時進行信號槽的綁定
下面是無參和有參的實例
import QtQuick
import QtQuick.ControlsWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")// Component.onCompleted: { print("窗口被創建")}// Component.onDestruction: {print("窗口被銷毀")}//接收者,接收信號后打印Rectangle{id:rec// Component.onCompleted: { print("矩形被創建")}// Component.onDestruction: {print("矩形被銷毀")}function ptr(){print("接收到按鈕信號")}function ptr2(a, b){print(a+b)}}//發送者,觸發后發送信號Button{width: 200height: 40x:50y:50text: "發送信號"signal testsignalsignal test2(int a,int b)onClicked: {testsignal()test2(1,2)}onTestsignal: ()=>{rec.ptr()}onTest2: (a,b)=>{rec.ptr2(a,b)}//有參信號連接的第二種方法親測無效,避雷//onTest2: rec.ptr2}}
還有一種連接方式
onClicked: {parent.testsignal.connect(rec.ptr)parent.test2.connect(rec.ptr2)}
?一般不會這么用,只是理解下用法,這里可能有重復鏈接的問題,qml5的用法,在qml6中已經廢除,qml6中改用connections,這里需要注意
QML5中的connections基本用法
import QtQuick 2.15
import QtQuick.Controls 2.15Item {signal mySignal()Button {text: "觸發信號"onClicked: mySignal()}Text {id: statusTexttext: "未收到信號"}// QML5 風格的 ConnectionsConnections {target: parent // 連接到此對象發出的信號onMySignal: {console.log("信號已接收")statusText.text = "已接收信號!"}}
}
QML5的connections沒有enable屬性?
QML6的基本用法
Connections {target: sourceObject // 發出信號的對象enabled: true // 可選,控制連接是否激活// 信號處理器 - 方式1:函數聲明function onSignalName(param1, param2) {// 處理邏輯}// 信號處理器 - 方式2:Lambda表達式onAnotherSignal: (param) => {// 處理邏輯}
}
組件的創建和銷毀
每個組件其實都有兩個信號,類似c++中類的構造函數和析構函數
Component.onCompleted:{}//組件的構造
Component.onDestruction: {}//組件的析構
在他們初始化和銷毀的時候就會發生
import QtQuick
import QtQuick.ControlsWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")Component.onCompleted: { print("窗口被創建")}Component.onDestruction: {print("窗口被銷毀")}Rectangle{Component.onCompleted: { print("矩形被創建")}Component.onDestruction: {print("矩形被銷毀")}}
}
運行效果:
按鈕點擊后控制臺輸出:
?
?在一個窗口里面創建一個矩形,窗口就是矩形的父對象,看看運行結果
初始化的時候是父節點先創建,在創建子節點,程序銷毀的時候是子節點先被銷毀,再是父節點被銷毀,和qtwidget的對象樹一樣
?