QML 信号与槽:直接绑定与跨文件通信

这篇介绍 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 || "等待信号发送 ..."
    }
}

关键逻辑解析

跨文件通信的核心是三步:

  1. 发信号 :在 CustomSender.qml 里用 signal sendValue(real value) 声明信号。
  2. 定义槽 :在 CustomReceiver.qml 里用 function slotReceiveMsg(msg) 定义普通函数作为槽。
  3. 做连接 :在主文件 Component.onCompleted 里用 sender.sendValue.connect(receiver.slotReceiveMsg) 把两者连起来。

这样做的好处是发送端和接收端互不知道对方存在,降低耦合。只要信号签名一致,随时可以替换不同的发送端或接收端。

对比表格

场景 推荐方式 原因
同文件内,一对一简单响应 onValueChanged 直接绑定 代码最短,关系直接
跨文件、多对一或需解耦 signal + connect 组件之间不直接依赖,便于复用

运行验证

  1. Qt Creator 打开示例的 CMakeLists.txt
  2. Ctrl+R 运行;
  3. 在第 1 个 demo 移动 Slider,观察 Text 实时变化;
  4. 切换到第 2 个 demo,移动 Sender 的 Slider,观察 Receiver 同步更新。

扩展复用方向

  • CustomSender 里增加 sendText(string text) 信号,把字符串传给 Receiver。
  • 一个 Sender 的多个信号可以分别 connect 到不同 Receiver,实现一对多广播。
  • disconnect 在页面销毁时断开连接,避免重复触发或内存问题。

已验证环境

相关推荐
GIS阵地2 小时前
QgsSingleBandPseudoColorRenderer 完整详解(QGIS 3.40.13 C++)
开发语言·前端·c++·qt·qgis
丰锋ff5 小时前
1.2 Qt常用基础类型
开发语言·qt
nianniannnn6 小时前
Qt QMessageBox知识点
开发语言·数据库·qt
J_yyy6 小时前
【Qt核心组件类框架】
开发语言·qt
Quz8 小时前
QML 网格与流式布局:Grid/GridLayout 与 Flow
qt
qq_401700419 小时前
Qt容器性能优化:QVector、QHash、QMap到底应该怎么选?
开发语言·qt·性能优化
Quz9 小时前
QML 线性布局:Row/RowLayout 与 Column/ColumnLayout
前端·qt
imatt1 天前
Qt Creator 在Windows下编译信息乱码
windows·qt
赤水无泪1 天前
qt中图标、名称的设置方式
开发语言·qt