ctk框架中的事件监听,即观察者模式流程上是这样:接收者注册监听事件->发送者发送事件->接收者接收到事件并响应;相比调用插件接口,监听事件插件间依赖关系更弱,不用指定事件的接收方和发送方是谁。
要使用ctk框架的事件服务,准备工作应该从cmake开始,编译出支持事件监听的动态库,Mac下的名称为liborg_commontk_eventadmin.dylib。本章要完成的内容是,从上章生成的主窗体中,以事件监听的方式调用一个子窗体。
加载EventAdmin动态库
添加动态库可以使用ctkPluginFrameworkLauncher,代码如下:main.cpp
ctkPluginFrameworkLauncher::addSearchPath("/Users/Shared/qt/ctkExample/libs");
ctkPluginFrameworkLauncher::start("org.commontk.eventadmin");
需要在框架加载前调用。
事件注册监听
首先编写我们需要的接收者模块,并注册监听事件,这里我们新建一个模块Client1,模块的接口处理参见章节二。plugin部分代码如下:
client1plugin.h
#ifndef CLIENT1PLUGIN_H
#define CLIENT1PLUGIN_H
#include <QObject>
#include "ctkPluginContext.h"
#include "service/event/ctkEventAdmin.h"
#include "service/event/ctkEventHandler.h"
#include "client1dlg.h"
class Client1Plugin : public QObject, public ctkEventHandler
{
Q_OBJECT
Q_INTERFACES(ctkEventHandler)
public:
Client1Plugin(ctkPluginContext *context);
protected:
void handleEvent(const ctkEvent& event);
signals:
void openDlg();
public slots:
void onOpenDlg();
private:
void registToMainWindow();
ctkPluginContext *m_context;
Client1Dlg* m_clientDlg;
};
#endif
client1plugin.cpp
#include "client1plugin.h"
#include <service/event/ctkEventConstants.h>
Client1Plugin::Client1Plugin(ctkPluginContext *context)
:m_context(context)
{
m_clientDlg = new Client1Dlg;
connect(this, SIGNAL(openDlg()), this, SLOT(onOpenDlg()),Qt::QueuedConnection);
//注册监听信号"zhimakaimen"
ctkDictionary dic;
dic.insert(ctkEventConstants::EVENT_TOPIC, "zhimakaimen");
context->registerService<ctkEventHandler>(this, dic);
}
void Client1Plugin::handleEvent(const ctkEvent& event)
{
//接收监听事件接口
if(event.getTopic() == "zhimakaimen")
{
emit openDlg();
//这里用了信号槽异步,因为线程中不能调用界面元素
}
}
与上一章自定义接口不同,这里我们实例化ctkEventHandler对象,并实现handleEvent接口。构造函数中注册的服务对象是ctkEventHandler,在注册时指定触发的事件,当事件触发时调用该对象的handleEvent实现指定操作。
事件发送
监听对象完成后调用比较简单,比如我们直接在窗体的菜单栏中,点击actoin调用,代码如下:mainwindowdlg.cpp
#include "mainwindowdlg.h" #include "ui_mainwindowdlg.h" #include "service/event/ctkEvent.h" #include "service/event/ctkEventAdmin.h" #include "service/event/ctkEventHandler.h" MainWindowDlg::MainWindowDlg(ctkPluginContext *context,QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindowDlg), m_context(context) { ui->setupUi(this); QAction* action = new QAction("用户1"); ui->menubar->addAction(action); connect(action, SIGNAL(triggered(bool)), this, SLOT(action_clicked())); } MainWindowDlg::~MainWindowDlg() { delete ui; } void MainWindowDlg::action_clicked() { //获取事件服务接口 ctkServiceReference ref; ctkEventAdmin* eventAdmin; ref = m_context->getServiceReference<ctkEventAdmin>(); if(ref) { eventAdmin = m_context->getService<ctkEventAdmin>(ref); m_context->ungetService(ref); } //发送事件 ctkDictionary message; if(eventAdmin) eventAdmin->postEvent(ctkEvent("zhimakaimen", message)); }