qml的信号槽机制和qtwidget差不多,但是使用方法不一样,qtwidget一般直接用connect函数把信号和槽一绑定就完事了,qml分为自动绑定和手动绑定。
信号自动绑定
在一个组件里面定义一个信号,用signal定义,当事件触发,比如button的onclick,发送信号,连接信号槽,就是这个信号发出后对他进行一个处理,边看例子边讲吧
//测试qml的信号槽机制
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
//文本框
Flickable {
id: flickable
anchors.centerIn: parent
width: 200
height: 200
contentWidth: textEdit.width
contentHeight: textEdit.height
clip: true
//滑动条部份,需要用flickable或者scrollbar包装起来
ScrollBar.vertical: ScrollBar {
id: vbar
width: 20
policy: ScrollBar.AsNeeded
anchors {
right: parent.right
top: parent.top
bottom: parent.bottom
}
}
TextEdit {
id: textEdit
width: flickable.width
height: Math.max(flickable.height, implicitHeight)
wrapMode: TextEdit.Wrap
color: "red"
}
}
//测试信号按钮
Button{
x:10
y:10
width: 40
height: 20
text: "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.Controls
Window {
width: 640
height: 480
visible: true
title: 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: 200
height: 40
x:50
y:50
text: "发送信号"
signal testsignal
signal 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.15
Item {
signal mySignal()
Button {
text: "触发信号"
onClicked: mySignal()
}
Text {
id: statusText
text: "未收到信号"
}
// QML5 风格的 Connections
Connections {
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.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Component.onCompleted: { print("窗口被创建")}
Component.onDestruction: {print("窗口被销毁")}
Rectangle{
Component.onCompleted: { print("矩形被创建")}
Component.onDestruction: {print("矩形被销毁")}
}
}
运行效果:
按钮点击后控制台输出:

在一个窗口里面创建一个矩形,窗口就是矩形的父对象,看看运行结果
初始化的时候是父节点先创建,在创建子节点,程序销毁的时候是子节点先被销毁,再是父节点被销毁,和qtwidget的对象树一样
323

被折叠的 条评论
为什么被折叠?



