该耦合器提供了一种事件机制,可以实现应用程序中松散耦合组件之间的通信。这种机制基于事件聚合器服务,允许发布者和订阅者通过事件进行通信,并且彼此之间仍然没有直接引用。简单来说就是提供了一个多播发布/订阅功能。

看上图了解事件耦合器。

Qt中自带的信号/槽也是一种解耦机制,但是当项目做大后要写好多connect来链接关系,有了事件耦合器后就不需要connect了。

1、创建事件

testeventargs.h:
#ifndef TESTEVENTARGS_H
#define TESTEVENTARGS_H#include "Event/baseeventargs.h"
class TestEventArgs : public BaseEventArgs
{
public:explicit TestEventArgs();int getId() const;void setId(int value);QString getName() const;void setName(const QString &value);QString toString();private:int id;QString name;};#endif // TESTEVENTARGS_Htesteventargs.cpp
#include "testeventargs.h"TestEventArgs::TestEventArgs() : BaseEventArgs()
{}int TestEventArgs::getId() const
{return id;
}void TestEventArgs::setId(int value)
{id = value;
}QString TestEventArgs::getName() const
{return name;
}void TestEventArgs::setName(const QString &value)
{name = value;
}QString TestEventArgs::toString()
{return QString("id=%1,name=%2").arg(id).arg(name);
}

2、订阅事件

//订阅
void Widget::on_btnSub_clicked()
{Function<void(TestEventArgs)> func(this, &Widget::dealEvent);EventAggregator::GetEvent<TestEvent>()->Subscribe(func);
}//处理事件
void Widget::dealEvent(TestEventArgs args)
{ui->label->setText(args.toString());
}

3、发布事件

//发布
void Widget::on_btnPub_clicked()
{TestEventArgs args;args.setId(1);args.setName("Test Event");EventAggregator::GetEvent<TestEvent>()->Puslish(args);
}

这样,一个发布/订阅的事件就完成了,也可以在任何时候取消事件注册,只需要调用Unsubscribe方法即可

EventAggregator::GetEvent<TestEvent>()->Unsubscribe(func);

源码:

baseeventargs.h

#ifndef DKBASEEVENTARGS_H
#define DKBASEEVENTARGS_H
#include <QFuture>/*** @brief 事件参数基类*/
class BaseEventArgs
{
public:~BaseEventArgs(){}bool isSync() const{return m_sync;}void setSync(bool sync){m_sync = sync;}private:/*** @brief 是否同步执行事件 true-同步 false-异步* 注:发布和订阅同一线程中既可以选择同步也可以选择异步,否则只能选择异步;异步调用中使用QMetaObject::invokeMethod*/bool m_sync = true;
};#endif // DKBASEEVENTARGS_H
eventaggregator.h
#ifndef DKEVENTAGGREGATOR_H
#define DKEVENTAGGREGATOR_H#include <QObject>
#include <QMap>
#include <QString>
#include <QMutex>/*** @brief 事件耦合器*/
class EventAggregator : public QObject
{Q_OBJECT/*** @brief 事件对象map(key-事件类型名,value-事件对象)*/static QMap<QString,QObject*> m_map;/*** @brief 互斥锁*/static QMutex *m_pMutex;
public:explicit EventAggregator(QObject *parent = nullptr);/*** @brief 获取模板类型的事件对象* @return 指定类型事件对象*/template<typename EventType>static EventType* GetEvent(){EventType *pEvent;QString className = typeid (EventType).name();if(m_map.contains(className)){pEvent = static_cast<EventType*>(m_map[className]);}else{pEvent = new EventType;m_pMutex->lock();m_map.insert(className,pEvent);m_pMutex->unlock();}return pEvent;}};#endif // DKEVENTAGGREGATOR_H

eventaggregator.cpp

#include "eventaggregator.h"EventAggregator::EventAggregator(QObject *parent) : QObject(parent)
{}QMap<QString,QObject*> EventAggregator::m_map = QMap<QString,QObject*>();QMutex* EventAggregator::m_pMutex = new QMutex();

eventbase.h

#ifndef DKEVENTBASE_H
#define DKEVENTBASE_H#include <QObject>/*** @brief 事件基类*/
class EventBase : public QObject
{Q_OBJECT
public:explicit EventBase(QObject *parent = nullptr);};#endif // DKEVENTBASE_H

eventbase.cpp

#include "eventbase.h"EventBase::EventBase(QObject *parent) : QObject(parent)
{}

function.h

#ifndef DKFUNCTION_H
#define DKFUNCTION_H#include <QUuid>
#include <functional>/*** @brief函数封装类*/
template<class T>
class Function
{
private:QUuid m_uuid;bool m_isEnable = true;
public:std::function<T> call;
public:Function(): m_uuid(QUuid::createUuid()){}Function(std::function<T> func): Function(){this->call = func;}template<typename t1, typename t2>Function(t1 pOwner, t2 pFunc): Function(){call = std::bind(pFunc, pOwner, std::placeholders::_1);}bool operator==(const Function& func){return this->m_uuid == func.m_uuid;}Function& operator=(const std::function<T>& func){call = func;return *this;}/*** @brief 设置成员变量函数* @param pOwner 成员函数所属对象指针* @param pFunc 成员函数指针*/template<typename t1, typename t2>void setMemberFunction(t1 pOwner, t2 pFunc){call = std::bind(pFunc, pOwner, std::placeholders::_1);}/*** @brief 设置普通函数、匿名函数和std::function类型仿函数* @param pFunc 函数指针*/template<typename t1>void setFunction(t1 pFunc){call = pFunc;}bool isEnable() const{return m_isEnable;}void setIsEnable(bool isEnable){m_isEnable = isEnable;}
};#endif // DKFUNCTION_H

pubsubevent.h

#ifndef DKPUBSUBEVENT_H
#define DKPUBSUBEVENT_H#include <QList>
#include <functional>
#include <QtConcurrent>
#include "Event/eventbase.h"
#include "Event/function.h"
#include "Event/baseeventargs.h"/*** @brief 订阅发布事件*/
template <class TPayload>
class PubSubEvent: public EventBase
{typedef Function<void(TPayload)> FuncType;
private:QList<FuncType> m_list;QMutex m_mutex;
public:PubSubEvent(QObject* parent = nullptr): EventBase(parent){}PubSubEvent& operator+=(FuncType func){m_mutex.lock();if(!m_list.contains(func)){m_list.append(func);}m_mutex.unlock();return *this;}PubSubEvent& operator-=(FuncType func){m_mutex.lock();m_list.removeOne(func);m_mutex.unlock();return *this;}void operator()(TPayload payload, bool isSync = true){BaseEventArgs& event = static_cast<BaseEventArgs&>(payload);event.setSync(isSync);for(auto dkFunc : m_list){if(isSync){dkFunc.call(payload);}else{QtConcurrent::run(dkFunc.call, payload);}}}/*** @brief 发布事件* @param payload 事件载体,即事件参数* @param isSync 是否同步执行*/void Puslish(TPayload payload, bool isSync = true){BaseEventArgs& eventArgs = static_cast<BaseEventArgs&>(payload);eventArgs.setSync(isSync);for(auto dkFunc : m_list){if(dkFunc.isEnable()){if(isSync){dkFunc.call(payload);}else{QtConcurrent::run(dkFunc.call, payload);}}}}/*** @brief 订阅事件* @param func 处理事件的函数*/void Subscribe(FuncType& func){m_mutex.lock();if(!m_list.contains(func)){m_list.append(func);}m_mutex.unlock();}/*** @brief 取消订阅事件* @param func 订阅事件的函数*/void Unsubscribe(FuncType& func){m_mutex.lock();m_list.removeOne(func);m_mutex.unlock();}
};#endif // DKPUBSUBEVENT_H

源码下载地址:

Qt事件耦合器示例程序-C++文档类资源-CSDN下载

Qt事件耦合器实现(类似C#的Prism中的事件耦合器)相关推荐

  1. mysql事件计划自动_逐步讲解MySQL中定时事件计划的创建

    一.使用过程1.查看当前是否已开启事件计划(调度器)有3种方法: SHOW VARIABLES LIKE 'event_scheduler'; SELECT @@event_scheduler; SH ...

  2. 浏览器中关于事件的那点事儿

    2019独角兽企业重金招聘Python工程师标准>>> 在前端中,有一个很重要的概念就是事件.我对于事件的理解就是使用者对浏览器进行的一个动作,或者说一个操作. 本文会介绍很多与事件 ...

  3. Python SolidWorks 二次开发—SolidWorks中的事件实现

    Python SolidWorks 二次开发-SolidWorks中的事件实现 文章目录 Python SolidWorks 二次开发---SolidWorks中的事件实现 前言 一.如何实现com事 ...

  4. jQuery中的事件机制深入浅出

    昨天呢,我们大家一起分享了jQuery中的样式选择器,那么今天我们就来看一下jQuery中的事件机制,其实,jQuery中的事件机制与JavaScript中的事件机制区别是不大的,只是,JavaScr ...

  5. echarts y轴添加点击事件_ECharts中的事件和行为

    用户在操作 Echarts 的图表时会触发相应的事件,这些事件由开发者监听,然后回调函数做出相应的处理,可以弹出一个对话框.跳转到一个地址或者做数据下钻等等. ECharts 3 中绑定事件跟 Ech ...

  6. 【EventBus】事件通信框架 ( 订阅类-订阅方法缓存集合 | 事件类型-订阅者集合 | 订阅对象-事件类型集合 )

    文章目录 前言 一.订阅类-订阅方法缓存集合 二.事件类型-订阅者集合 三.订阅对象-事件类型集合 前言 首先声明几个数据结构 , 参考 [EventBus]EventBus 源码解析 ( 注册订阅者 ...

  7. 再次理解javascript中的事件

    一.事件流的概念 + 事件流描述的是从页面中接收事件的顺序. 二.事件捕获和事件冒泡 +    事件冒泡接收事件的顺序: +   事件捕获接收事件顺序: +   IE中的事件流叫事件冒泡,IE中没有事 ...

  8. JavaScript中的事件处理程序

    JavaScript和HTML之间的交互是通过事件实现的.事件,就是文档或者浏览器窗口中发生的一些特定的交互瞬间.可以使用事件处理程序来预订事件,以便在事件发生的时候执行响应的代码.这种观察者模式的模 ...

  9. js中event事件对象

    1. event事件 概念: Event 对象代表事件的状态,当dom tree中某个事件被触发的时候,会同时自动产生一个用来描述事件所有的相关信息(比如事件在其中发生的元素.键盘按键的状态.鼠标的位 ...

最新文章

  1. 蒙特卡洛粒子滤波定位算法_粒子滤波——来自哈佛的详细的粒子滤波器教程【1】...
  2. Windows DDK介绍,选择和安装
  3. 反弹端口 HTTP代理 HTTP隧道技术
  4. Linux vim开启/关闭代码着色(高亮显示)
  5. 安卓toast文字提示
  6. php函数库快速记忆法_PHP速成大法
  7. python pandas read_csv 迭代器使用方法_pandas.read_csv参数详解(小结)
  8. Python格式化函数format详解
  9. 关于spark structed stream 流中的触发trigger间隔的理解
  10. 【易语言界面开发系列教程之(EX_UI使用系列教程(12)--EX组件(列表框EX))】
  11. 图片飞出去的特效怎么做?3分钟AE制作教程
  12. rabbitmq消息队列原理
  13. 恢复未保存的word
  14. 模拟信号数字化传输系统的设计与仿真分析说明书
  15. java 判断日期周几_Java判断当前日期是否在周几到周几时间范围内
  16. 开发与研发:区别很大(上)
  17. 快速掌握PS通道抠头发“七步法”
  18. 漫谈核心能力(2) -- 知错能改,善莫大焉
  19. 高德地图实现展示多个规划的路线
  20. h5实现上下滑动切页

热门文章

  1. python 安装spyder和问题
  2. 邮箱大师支持html,网易邮箱大师pc版
  3. 做一个女孩喜欢的绅士男人
  4. homebrew/dupes was deprecated. This tap is now empty as all its formulae were migrated
  5. IoT黑板报0207:MU-MIMO技术让网络龟速变神速
  6. chatty: uid=10549(u0_a549) com.exampleidentical 40 lines
  7. 聊聊 iOS 15 新特性
  8. 用python绘制熊猫图案,在python中绘制熊猫系列的CDF
  9. 学会这一招,轻松处理图片转ico格式
  10. Me-tetrazine-Disulfo-Cyanine5,甲基四嗪-磺酸基菁染料Cy5,蓝色固体