这篇介绍 QML 内部两种最常见的信号用法:控件属性变化时直接响应,以及把多个 QML 文件里的组件串起来通信。
- 直接绑定 --- 用
onValueChanged响应 Slider 数值变化 - 跨文件通信 --- 用
connect把 CustomSender 的信号接到 CustomReceiver 的槽函数
Demo 1 直接绑定
移动 Slider 滑块时,下方 Text 实时显示当前数值。

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
id: root
property string respMsg: ""
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 120
color: "#fff"
border.color: "#ccc"
border.width: 1
radius: 6
ColumnLayout {
anchors.fill: parent
anchors.margins: 10
spacing: 10
Text {
text: "请移动滑块触发信号: "
color: "#333"
font.pointSize: 12
font.bold: true
}
Slider {
id: slider
Layout.fillWidth: true
from: 0
to: 100
value: 50
onValueChanged: {
root.respMsg = "滑块数值:" + value.toFixed(2)
}
}
Text {
id: textReceiver
text: root.respMsg || "等待显示响应数据 ..."
font.pointSize: 11
color: "#3498db"
wrapMode: Text.WordWrap
}
}
}
Item { Layout.fillHeight: true }
}
}
关键逻辑解析
QML 里每个属性都自带一个 <属性名>Changed 信号。Slider 的 value 属性变化时,onValueChanged 处理器就会被触发。
这里把响应逻辑直接写在控件内部,适合一对一、同文件内的简单交互。代码少,关系清晰:滑块动 → respMsg 更新 → Text 刷新。
如果多个地方都要监听这个 value,直接写多个 onValueChanged 会重复。更解耦的做法是把 Slider 的信号 connect 到外部的槽函数,这就是下个 demo 的思路。
Demo 2 跨文件信号通信
CustomSender.qml 发送滑块数值,CustomReceiver.qml 接收并显示,两个组件互不直接引用,靠主文件在初始化时做连接。

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
id: root
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
CustomSender {
id: sender
}
CustomReceiver {
id: receiver
}
Component.onCompleted: {
sender.sendValue.connect(receiver.slotReceiveMsg)
}
Item { Layout.fillHeight: true }
}
}
CustomSender.qml:
qml
Rectangle {
id: root
signal sendValue(real value)
// ... 省略布局与样式 ...
Slider {
id: slider
from: 0
to: 100
value: 50
onValueChanged: {
root.sendValue(value)
}
}
}
CustomReceiver.qml:
qml
Rectangle {
id: root
property string message: ""
function slotReceiveMsg(msg) {
root.message = "来自sender发送的数据: " + msg.toFixed(2)
}
// ... 省略布局与样式 ...
Label {
text: root.message || "等待信号发送 ..."
}
}
关键逻辑解析
跨文件通信的核心是三步:
- 发信号 :在
CustomSender.qml里用signal sendValue(real value)声明信号。 - 定义槽 :在
CustomReceiver.qml里用function slotReceiveMsg(msg)定义普通函数作为槽。 - 做连接 :在主文件
Component.onCompleted里用sender.sendValue.connect(receiver.slotReceiveMsg)把两者连起来。
这样做的好处是发送端和接收端互不知道对方存在,降低耦合。只要信号签名一致,随时可以替换不同的发送端或接收端。
对比表格
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 同文件内,一对一简单响应 | onValueChanged 直接绑定 |
代码最短,关系直接 |
| 跨文件、多对一或需解耦 | signal + connect |
组件之间不直接依赖,便于复用 |
运行验证
- Qt Creator 打开示例的
CMakeLists.txt; - 按
Ctrl+R运行; - 在第 1 个 demo 移动 Slider,观察 Text 实时变化;
- 切换到第 2 个 demo,移动 Sender 的 Slider,观察 Receiver 同步更新。
扩展复用方向
- 在
CustomSender里增加sendText(string text)信号,把字符串传给 Receiver。 - 一个 Sender 的多个信号可以分别 connect 到不同 Receiver,实现一对多广播。
- 用
disconnect在页面销毁时断开连接,避免重复触发或内存问题。
已验证环境:
- Qt 版本:Qt 6.8.2
- 操作系统:Windows 11
- GitHub:QML-Minimal-Demos/qml_signals