观察者模式详解:用 Qt 信号与槽机制深入理解

从信号与槽机制看Qt的事件驱动设计哲学 本文深入探讨了Qt框架中信号与槽机制的设计哲学及其在事件驱动编程中的核心作用。通过分析QPushButton等控件的实战应用,揭示了Qt如何通过元对象系统实现松耦合通信,并提供了性能优化和现代C++集成的实用技巧。文章特别强调了信号与槽在实现观察者模式和中介者模式时的天然优势,为开发者提供了高效的事件驱动解决方案。 阅读详情

引言

你是否曾遇到这样的需求:一个对象的状态发生变化后,希望通知其他对象进行相应的更新?比如:

  • 新闻订阅系统:当新闻发布后,所有订阅者都会收到通知。
  • 股票行情推送:股价变化时,所有关注该股票的投资者都会收到更新信息。
  • Qt 界面开发:按钮被点击时,窗口应该发生某些变化。

这些场景都适用于观察者模式(Observer Pattern)。

在本篇文章中,我们不仅讲清楚观察者模式的结构,还会用 Qt 的信号与槽机制 来深入解析,让你真正理解这一模式的奥秘!


1. 什么是观察者模式?

观察者模式是一种 一对多 的设计模式,允许多个对象(观察者)监听某个对象(被观察者)的状态变化,并在变化时收到通知。

简单来说:

  • 被观察者(Subject):负责维护一个观察者列表,并在状态发生变化时通知所有观察者。
  • 观察者(Observer):接收被观察者的通知并做出相应反应。

现实例子:

场景被观察者(Subject)观察者(Observer)
微信公众号订阅公众号订阅的用户
股票市场股票关注股票的投资者
UI 界面按钮点击按钮(QPushButton)监听点击的槽函数

2. 观察者模式的结构

观察者模式一般包括以下角色:

  1. Subject(被观察者):

    • 维护一个观察者列表(即谁在关注它)。
    • 当自身状态发生变化时,通知所有观察者。
  2. Observer(观察者):

    • 订阅 Subject,并实现 update() 方法,接收状态变化通知。
  3. 通知机制:

    • Subject 需要提供 attach() 和 notify() 方法,管理观察者并进行通知。

观察者模式 UML 结构图

+-------------+       +----------------+
|  Observer   |<------|    Subject     |
+-------------+       +----------------+
| +update()   |       | +attach()      |
|             |       | +detach()      |
|             |       | +notify()      |
+-------------+       +----------------+

3. 传统 C++ 实现观察者模式

在 C++ 中,我们可以用 vector 存储观察者列表,并手动通知它们:

传统 C++ 实现

#include <iostream>
#include <vector>

// 观察者接口
class Observer {
public:
    virtual void update(int value) = 0;
};

// 被观察者(Subject)
class Subject {
private:
    std::vector<Observer*> observers;
    int state;

public:
    void attach(Observer* observer) { observers.push_back(observer); }
    void notify() {
        for (Observer* obs : observers) {
            obs->update(state);
        }
    }

    void setState(int value) {
        state = value;
        notify();
    }
};

// 具体观察者
class ConcreteObserver : public Observer {
public:
    void update(int value) override {
        std::cout << "Observer received update: " << value << std::endl;
    }
};

int main() {
    Subject subject;
    ConcreteObserver observer1, observer2;

    subject.attach(&observer1);
    subject.attach(&observer2);

    subject.setState(42);  // 触发通知
}

问题:

  • 需要手动管理 Observer 的列表。
  • notify() 需要手动遍历所有观察者,不够灵活。
  • 可能会出现空指针问题(被观察者销毁后,观察者仍在使用)。

4. 用 Qt 信号与槽实现观察者模式

Qt 提供了一种更强大、更安全的实现方式——信号(Signal)与槽(Slot)机制。它本质上就是观察者模式的扩展,但更加灵活和易用!

在这里插入图片描述

信号与槽如何实现观察者模式?

观察者模式角色Qt 信号与槽对应
Subject(被观察者)QObject + Signal
Observer(观察者)QObject + Slot
通知机制connect()

Qt 实现观察者模式

#include <QObject>
#include <QDebug>

// 被观察者(Subject)
class Subject : public QObject {
    Q_OBJECT

signals:
    void valueChanged(int newValue);  // 信号(事件)

public:
    void setValue(int value) {
        emit valueChanged(value);  // 触发信号,通知观察者
    }
};

// 观察者(Observer)
class Observer : public QObject {
    Q_OBJECT

public slots:
    void onValueChanged(int newValue) {
        qDebug() << "Observer received new value:" << newValue;
    }
};

int main() {
    Subject subject;
    Observer observer;

    // 连接信号和槽
    QObject::connect(&subject, &Subject::valueChanged, &observer, &Observer::onValueChanged);

    // 触发事件
    subject.setValue(42);
}

Qt 信号与槽 vs 传统观察者模式

对比项传统观察者模式Qt 信号与槽
观察者管理方式需手动维护列表自动管理
触发方式直接调用 update()emit 发送信号
线程安全需要手动同步Qt::QueuedConnection 支持多线程
解除连接需要手动移除观察者disconnect() 轻松解绑

5. 信号与槽让观察者模式更强大

  1. 自动管理连接,避免空指针错误。
  2. 支持跨线程通信,不需要额外的同步机制。
  3. 更灵活:可以在运行时动态连接和解除连接。
  4. 更易读:代码清晰,不需要手动维护 std::vector<Observer*>。

6. 观察者模式如何运用到实际开发中?

1. UI 界面更新

  • 当数据变化时,自动更新 UI 界面(如 QLabel、QProgressBar)。
QObject::connect(&subject, &Subject::valueChanged, ui->label, &QLabel::setText);

2. 多线程任务通知主线程

  • 通过 Qt::QueuedConnection 让后台线程通知主线程刷新 UI。

3. 事件驱动开发

  • Qt 本身就是事件驱动的,信号与槽大幅减少了回调函数的使用。

7. 总结

  • 观察者模式解决了 对象间的事件通知 问题。
  • Qt 信号与槽机制 是观察者模式的高级实现,提供自动管理、类型安全、跨线程支持。
  • 在 Qt 开发中,几乎所有 UI 组件、后台任务、事件响应都基于 信号与槽。

你学会了吗? 🎯 如果有疑问,欢迎讨论! 🚀

Qt面试必问:信号与槽机制详解(附常见面试题解析) 本文深度解析Qt核心通信机制——信号与槽,从元对象系统(moc)原理、连接类型(如DirectConnection与QueuedConnection)的线程安全差异,到自定义信号槽设计、性能陷阱及最佳实践,帮助开发者应对面试挑战并编写更健壮的Qt应用。 阅读详情

相关推荐

【QT进阶指南】QT信号与槽:深入理解emit的实战应用与最佳实践

本文深入探讨了QT信号与槽机制中emit的实战应用与最佳实践。通过跨线程通信、多窗口数据同步等典型场景,详细解析了emit信号的使用技巧与性能优化方案,帮助开发者掌握QT事件处理的核心技术,提升代码质量与运行效率。

weixin_30764771的博客 376

C++ 设计模式(三)——观察者模式

观察者模式,C++版

一个程序猿的工作知识深化日常 1286

带你了解Qt框架中的设计模式:观察者模式

作者:令狐掌门技术交流QQ群:675120140。

琅嬛福地 1598

设计模式之观察者模式(C++)

介绍设计模式之观察者模式

翟天保的博客 1万+

QT插件框架深入理解与实践

Qt框架的一个显著特点是其模块化设计,这使得开发者能够根据需要选择特定的模块。模块化设计是Qt框架的核心,它简化了整个应用程序的构建过程,同时也促进了代码的复用。Qt框架由一系列功能强大、模块化的库组成,这些库通过一组定义良好的C++接口进行交互。Qt模块通常包含针对特定功能的类和函数集合。每个模块都通过一个独立的库文件(.lib或.so文件)来提供支持,开发者可以根据其项目需求进行模块选择。例如,如果需要进行GUI程序开发,则需要包含QtWidgets模块;如果需要网络通信,则需要引入。

weixin_35734408的博客 1037

Qt实现全局观察者模式(多层窗体之间直接传递消息)

多个窗体之间要通信真的好麻烦,比如:A调出B,B调出C,那么C给A发消息,那就得经过B周转才能实现。对于两三层窗体,这种方法还可以接受,但嵌套太多就有点烦人了。

Qt中,信号与槽的原理及观察者模式的应用

连接可以通过QObject的connect()函数来创建,该函数接收信号源对象、信号的名称、槽函数的目标对象和槽函数的名称作为参数。通过将信号与槽函数进行连接,当信号被发射时,与之连接的槽函数将被调用。一个对象可以发射多个信号,多个对象可以连接到同一个信号上,一个对象可以连接多个槽函数,甚至还可以在不同线程中进行信号与槽之间的通信。在该模式中,当一个对象的状态发生变化时,它会自动通知所有依赖于它的其他对象,使它们能够及时作出相应的响应。它基于观察者模式,通过发射信号和连接槽函数来实现对象之间的通信。

weixin_49146002的博客 2518

Python逆向爬取Tik Tok,MsToken,X-Bogus以及signature

tiktok作为字节海外的自媒体平台,具有很非常大的价值,本文旨在教会大家实现Tik Tok的签名获取以及数据的最终爬取。

weixin_74305707的博客 3268

QT设计模式:观察者模式

观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,会通知所有的观察者对象,使它们能够自动更新自己的状态。

buhuiCyvyan的博客 1018

一文搞定学术英语写作 (斯坦福SCI论文写作课程笔记)

0.前言: 本文基于斯坦福Kristin Sainani 教授的学术论文写作公开课——SCI论文写作(Writing in the Sciences)。在此基础上进行章节顺序的重排及部分内容的删减,以方便第一次进行英语学术论文写作的同学快速上手。 时间充足和想要系统学习英文学术写作的同学,十分建议观看完整课程视频,一定会受益匪浅!课程地址如下: 课程B站地址:https://www.bilibili.com/video/BV1zv41177JQ 1.论...

Ogmx的博客 3万+

避坑指南:LAMMPS做GCMC模拟时,化学势mu和压力p到底怎么设?

本文详细解析了LAMMPS中巨正则蒙特卡洛(GCMC)模拟的关键参数设置,特别是化学势(mu)与压力(p)的正确计算方法。通过理论分析、实用公式和黄金法则,帮助用户避免常见误区,提升模拟精度和效率,适用于各类复杂体系的分子模拟研究。

weixin_42525289的博客 428

深入理解Qt信号槽机制

深入理解Qt信号槽机制

m0_60259116的博客 1287

把“思考”塞进 1 KB:我用纯 C 语言给单片机手搓了一个微型 Transformer 推理引擎

摘要:本文探讨了在64KB SRAM的MCU(如STM32H743)上部署精简Transformer模型的技术方案。通过将6层Transformer压缩至1层(隐藏维度128)、4-bit KV-Cache量化等优化手段,实现了240KB Flash占用和59KB RAM峰值,推理延迟184ms(400MHz Cortex-M7),准确率96.1%。关键创新包括:手工优化矩阵乘(CMSIS-NN)、查表法Softmax/LayerNorm、权重按Tile重排提升Cache命中率(60%→94%)。

qq_74383080的博客 2921

高级Qt信号槽编程技巧

Qt核心概念和机制介绍高级Qt信号槽编程技巧,Qt核心概念与机制详解引言,在深入探讨Qt中高级信号槽编程技巧之前,我们先对Qt的核心概念及其工作机制进行一番了解。Qt是一个跨平台的应用程序开发框架,广泛应用于桌面、移动和嵌入式设备上。其设计思想强调了组件化、模块化的理念,并通过强大的信号与槽机制为开发者提供了一种高效灵活的事件处理方式。Qt的信号与槽机制,信号与槽的基本概念,在Qt中,信号是一种特殊的对象成员函数,可以被其他对象连接或监听。

QT性能优化QT原理源码QT界面美化 1393

一文快速教你如何下载国自然模版

5. 成功进入“相关文件查看”页面后,点击左侧的“项目申请文件“,如果你此次申请的是“面上项目”,选择对应的下拉框,找到对应的模版下载即可。6. 🫑们发现,在当前页面点击“青年科学基金项目”,左侧出现的是“原国家杰出青年科学基金项目”。7. 进入下一页后,点击“青年科学基金项目”,便可以在右侧找到🫑们要找的模版啦。2. 成功登陆后,点击1处的“首页”,在首页界面,再点击2处的“项目批准”。8. 点击上图3处的“文件详情”,就可以找到可以下载的模版啦(如下图)。3. 从“项目批准”进入后,点击“管理”。

薰珞婷紫小亭子的博客 2396

【全志V821_FoxPi】6-2 IMX219 MIPI摄像头适配

全志V821芯片适配IMX219 MIPI摄像头(2lane)教程,基于FoxPi开发板V1.2 SDK。文章详细介绍了IMX219的技术参数(800万像素、1/4英寸CMOS、支持1080P@30fps输出)及模组接口原理图。重点展示了设备树配置方法,包括PIO引脚定义(TWI0使用PA3/PA4,复位引脚PA2)、TWI0节点设置(100kHz时钟)以及VIND0节点中sensor0的完整配置(I2C地址0x20、MCLK0、RAW格式输出等)。配置过程强调需注意IMX219的器件地址转换(0x10→0

第四维度的博客 2248

Qt信号与槽机制:原理、应用与性能优化

信号与槽是Qt框架实现对象间通信的核心机制,采用发布-订阅模式解耦组件关系。从原理上看,它通过元对象系统实现类型安全的动态绑定,相比传统回调函数具有更好的封装性和线程安全性。在GUI编程中,信号槽机制能优雅处理事件响应、跨窗口通信等场景,同时支持Lambda表达式等现代C++特性。对于高频调用的场景,可通过直接连接、信号合并等方式优化性能。结合QML使用时,信号槽还能实现声明式的界面逻辑绑定,是Qt开发中不可或缺的重要技术。

weixin_33682790的博客 348

【Unity 实用工具篇】| Unity中 实现背景模糊效果,简单易用

背景模糊 是一个很实用的功能,它可以帮助游戏在视觉上有更好的专注力和表现力。 实现模糊的种类和方式有很多种,大家自行选择适合自己的就可以了。 下面一起来看下本文实现背景模糊的效果和使用方式吧!

努力前行,总会成为自己心中的那道光 4万+

Qt的信号与槽

在GUI编程中,组件组件如何实现通信是核心的技术内容。 Qt使用了信号与槽的机制,为此Qt引入了一些关键字slots、signals、emit,这些都是Qt特有的关键字,然后这些关键字会被Qt的moc转换位标准的C++语句。...

Albert_weiku的博客 4827

基于AI大模型实现自然语言转SQL、SQL解释、SQL优化和SQL转换

随着大数据和人工智能技术的发展,数据分析和数据挖掘在各行各业中的应用越来越广泛。SQL(Structured Query Language)作为关系数据库的查询语言,是数据分析的重要工具。然而,SQL语言的复杂性和专业性使得许多非技术背景的用户难以直接使用,阻碍了数据的广泛利用。为了降低SQL的使用门槛,许多研究者和企业开始探索如何通过自然语言处理(NLP)技术,将自然语言转化为SQL查询语句,从而让用户可以通过自然语言与数据库进行交互。

AI天才研究院 2238

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

深入理解信号与槽

信号和槽机制是Qt编程的基础 1.信号和槽原理 信号与槽是Qt对象间通信的一种机制,是Qt的核心特性,也是Qt与其他应用框架最显著的区别。 在GUI编程中,当我们操作控件时,我们希望其他控件能知道作出反应,或者任何对象都可以和其他对象通信,简单来说,就是点击最大化,调用了MAX()这函数。 在有些较老的GUI框架中,实现这种通信是采用回调函数。回调函数是C语言函数的一种应用,但是回调函数存在两个缺陷。 我们不能保证持有回调函数的业务处理函数会使用正确的参数来调用回调函数的指针。 回调函数使得业务处理函数和

一个不甘于此的弱鸡 866

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

深入理解信号槽机制

深入理解信号槽(一) 这篇文章来自于 A Deeper Look at Signals and Slots,Scott Collins 2005.12.19。需要说明的是,我们这里所说的“信号槽”不仅仅是指 Qt 库里面的信号槽,而是站在一个全局的高度,从系统的角度来理解信号槽。所以在这篇文章中,Qt 信号槽仅仅作为一种实现来介绍,我们还将介绍另外一种信号槽的实现——boost::signal。因此,当你在文章中看到一些信号的名字时,或许仅仅是为了描述方便而杜撰的,实际并没有这个信号。 什么是信号槽?

顺其自然~专栏 3068

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C++信号与槽机制:从原理到实现,构建松耦合通信系统

在C++软件架构中,对象间通信是构建松耦合系统的核心挑战。传统回调函数存在类型安全差、生命周期管理复杂等问题,而观察者模式为解决这类问题提供了理论基础。通过结合现代C++特性,我们可以实现更优雅的通信机制。其技术原理主要基于函数对象封装、模板元编程和智能指针生命周期管理,利用`std::function`封装可调用对象,通过可变参数模板支持任意参数列表,并借助`std::weak_ptr`实现自动连接清理。这种机制的技术价值在于提升代码模块化、增强类型安全并简化多对象间的事件通知。在应用场景上,它广泛适用于

weixin_33146151的博客 286

深入理解信号槽

<br />在豆子空间 http://devbean.blog.51cto.com 中发现的,总结的很好,在此记录一下,共4篇文章<br /> <br />深入理解信号槽(一) http://devbean.blog.51cto.com/448512/417658<br />深入理解信号槽(二) http://devbean.blog.51cto.com/448512/424778<br />深入理解信号槽(三) http://devbean.blog.51cto.com/448512/426999<br

Embedded Linux Development 1579

QT 中的元对象系统(四):信号槽机制深入理解

信号槽(Signals and Slots)是 Qt 框架中用于对象间通信的核心机制,它为开发者提供了一种灵活、类型安全且高效的方式来实现对象间的交互。clicked()信号槽是观察者模式的一种实现,特性如下:A、一个信号就是一个能够被观察的事件,或者至少是事件已经发生的一种通知;B、一个槽就是一个观察者,通常就是在被观察的对象发生改变的时候——也可以说是信号发出的时候——被调用的函数;C、信号与槽的连接,形成一种观察者-被观察者的关系;D、当事件或者状态发生改变的时候,信号就会被发出;

红军不怕远征难,万水千山只等闲 696
上一篇: Qt 关键技术点总结与实践经验
下一篇: 深入学习恩智浦 GoPoint:探索 AI Demo 与嵌入式 AI 开发
嵌入式孙老师
博客等级 码龄7年 5686粉丝 898原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值