CTK插件框架学习-事件监听(07)

news2025/2/7 4:01:05

CTK插件框架学习-服务工厂(06)icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/137295686

一、简介

事件监听指当事件发生变化时所产生的通信,是动态的,对于已经发生过的事件无法监听

二、事件类型

1、框架事件

监听框架状态变化,因为监听在框架初始化之后所以只能监听框架结束事件

事件类型
FRAMEWORK_STARTED
PLUGIN_ERROR
PLUGIN_WARNING
PLUGIN_INFO
FRAMEWORK_STOPPED
FRAMEWORK_STOPPED_UPDATE
FRAMEWORK_WAIT_TIMEDOUT

2、插件事件

监听插件状态变化,如插件安装,插件启动

事件类型
INSTALLED
RESOLVED
LAZY_ACTIVATION
STARTING
STARTED
STOPPING
STOPPED
UPDATED
UNRESOLVED
UNINSTALLED

3、服务事件

在服务内进行插件注册、销毁等触发

事件类型
REGISTERED
MODIFIED
MODIFIED_ENDMATCH
UNREGISTERING

三、监听功能测试

EventListener类

============================EventListener.h==================================
#pragma once
#include <QObject>
#include <ctkPluginFrameworkEvent.h>
#include <ctkPluginEvent.h>
#include <ctkServiceEvent.h>

class EventListener :
	public QObject
{
	Q_OBJECT
			   
public:
	explicit EventListener(QObject *parent = Q_NULLPTR);
	~EventListener();

public slots:
	void slotFrameWorkEvent(const ctkPluginFrameworkEvent& event);
	void slotPluginEvent(const ctkPluginEvent& event);
	void slotServiceEvent(const ctkServiceEvent & event);
};


============================EventListener.cpp================================

#include "EventListener.h"
#include <qdebug.h>

EventListener::EventListener(QObject * parent)
{
}

EventListener::~EventListener()
{
}

void EventListener::slotFrameWorkEvent(const ctkPluginFrameworkEvent & event)
{
	if (event.isNull())
	{
		qDebug() << event.getPlugin()->getSymbolicName() << ": " << event.getErrorString();
		return;
	}

	qDebug() << event.getPlugin()->getSymbolicName() << ": " << event.getType();
}

void EventListener::slotPluginEvent(const ctkPluginEvent & event)
{
	if (event.isNull())
	{
		qDebug() << event.getPlugin()->getSymbolicName() << "is null";
		return;
	}

	qDebug() << event.getPlugin()->getSymbolicName() << ": " << event.getType();
}

void EventListener::slotServiceEvent(const ctkServiceEvent  & event)
{
	if (event.isNull())
	{		
		qDebug() << "ctkServiceEvent is null";
		return;
	}
	ctkServiceReference ref = event.getServiceReference();
	QSharedPointer<ctkPlugin> plugin = ref.getPlugin();
	qDebug() << plugin->getSymbolicName() << ": " << event.getType() << " usingPlugins:" << ref.getUsingPlugins();
}

main.cpp

#include "CTKPlugin.h"
#include <QtWidgets/QApplication>


#include <iostream>
#include <QStyleFactory>
#include <QDir>
#include <QDirIterator>
#include <QDebug>

#include "ctkPluginFrameworkFactory.h"
#include "ctkPluginFramework.h"
#include "ctkPluginException.h"
#include "ctkPluginContext.h"
#include "ctkPluginFrameworkLauncher.h"

#include "EventListener.h"

#include "../TestPlugin/iTestPlugin.h"
#include "../TestPlugin2/IService1.h"
#include "../TestPlugin2/IService2.h"
#include "../TestPlugin3/IService.h"
#include "../TestServiceFactory/IPrintfService.h"

/*
* 1、注意:Plugin-SymbolicName要满足这里的前缀是:TARGET/META-INF格式。TARGET的名字最好和工程名一致,不然可能出现device not open错误。
* 2、如果CTK初始化、插件安装启动等是在一个类中,则与CTK相关的变量应定义成类的属性,不能是成员变量,否则获取不到服务
* 3、CTK插件组成:
(1)每个插件有自己的注册器Activator,继承自QObject和ctkPluginActivator的一个类,并实现ctkPluginActivator的start、stop函数
(2)每个插件必须有一个资源文件,名称一般与插件名称一致,前缀必须为TARGET/META-INF,例:插件名称/META-INF
(3)每个插件必须添加一个元数据文件,名字必须为MANIFEST.MF,并添加到资源文件中
* 4、QSharedPointer framework这个对象既可以作为对象也可以作为对象指针,但要作为插件框架使用必须要用指针方法调用
* 5、生成的插件名(TARGET)不要有下划线,因为CTK会默认将插件名中的下划线替换成点号,最后导致找不到插件
*/

int main(int argc, char *argv[])
{
	QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication a(argc, argv);
	a.setApplicationName("ctktest");//Linux下没有名称报错

	QString path = QCoreApplication::applicationDirPath();

	//启用通信插件框架
#ifdef _DEBUG
	ctkPluginFrameworkLauncher::addSearchPath(path + "/CTKPlugins");
	//ctkPluginFrameworkLauncher::addSearchPath("E:/Demo(Qt5)/08_CTKPlugin/CTKPlugin/CTK/lib/ctk-0.1/plugins");
#else
	ctkPluginFrameworkLauncher::addSearchPath(path + "/CTKPlugins");
#endif // _DEBUG
	// 设置并启动 CTK 插件框架
	try {
		ctkPluginFrameworkLauncher::start("org.commontk.eventadmin");
	}
	catch (ctkException e)
	{
		std::cout << e.message().toStdString() << std::endl;
	}

	// 启动插件工厂
	ctkPluginFrameworkFactory* ctkFrameWorkFactory = new ctkPluginFrameworkFactory;
	QSharedPointer<ctkPluginFramework> framework = ctkFrameWorkFactory->getFramework();
	try {
		framework->init();
		framework->start();
	}
	catch (const ctkPluginException& e)
	{
		std::cout << "framework init fail" << std::endl;
	}

	//在框架初始化启动成功后再调用事件监听
	EventListener eventListener;
	framework->getPluginContext()->connectFrameworkListener(&eventListener, SLOT(slotFrameWorkEvent(ctkPluginFrameworkEvent)));
	framework->getPluginContext()->connectPluginListener(&eventListener, SLOT(slotPluginEvent(const ctkPluginEvent&)));
	framework->getPluginContext()->connectServiceListener(&eventListener, "slotServiceEvent");

	//QString dir = QCoreApplication::applicationDirPath();
	//dir += "/plugins/TestPlugin.dll";
	//QUrl url = QUrl::fromLocalFile(dir);
	QSharedPointer<ctkPlugin> plugin;
#if 1
	QDirIterator iter(path + "/plugins/", { "*.dll" }, QDir::NoFilter, QDirIterator::Subdirectories);
	while (iter.hasNext()) {
		//qDebug() << iter.next();
		QString dllPath = iter.next();
		QUrl url = QUrl::fromLocalFile(dllPath);
		try
		{
			plugin = framework->getPluginContext()->installPlugin(url);
			qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
			
			//获取MANIFEST.MF中的数据
			QHash<QString, QString> headers = plugin->getHeaders();
			ctkVersion version = ctkVersion::parseVersion(headers.value(ctkPluginConstants::PLUGIN_VERSION));
			QString name = headers.value(ctkPluginConstants::PLUGIN_NAME);
		}
		catch (ctkPluginException e) {
			std::cout << e.message().toStdString() << e.getType() << std::endl;
		}

		try {
			plugin->start(ctkPlugin::START_TRANSIENT);//表示立即启用插件,不设置参数的话加载后也不会立即打印输出
			qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
		}
		catch (ctkPluginException e) {
			std::cout << e.message().toStdString() << e.getType() << std::endl;
		}
	}
#else

	
#endif


	ctkServiceReference ref = framework->getPluginContext()->getServiceReference<IPrintfService>();
	if (ref)
	{
		IPrintfService* service = qobject_cast<IPrintfService*>(framework->getPluginContext()->getService(ref));
		if (service != nullptr)
		{
			service->printf();
		}
	}

	//ctkPlugin::State sta = plugin->getState();
	//ctkPluginFrameworkLauncher::stop();
	//plugin->stop(); 
	//plugin->uninstall();
	//sta = plugin->getState();


	CTKPlugin c;
	c.show();
    return a.exec();
}

CTK插件框架学习-服务追踪(08)icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/137799296

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1598500.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ARFoundation自学01】搭建AR框架,检测平面点击位置克隆物体

Unity开发ARFoundation相关应用首先安装ARFoundation包 然后设置XR 1.基础AR场景框架搭建 2.一个基本的点击克隆物体到识别的平面脚本 挂在XROrigin上 脚本AppController 脚本说明书 ## 业务逻辑 AppController 脚本旨在实现一个基本的 AR 应用程序功能&#xff1a;用户通过…

【24年物联网华为杯】赛题分析与初步计划

赛事介绍 官网链接&#xff1a;2024 年全国大学生物联网设计竞赛 (sjtu.edu.cn) 含金量&#xff1a;属于A类赛事 &#xff08;注意&#xff1a;很多搜索结果的序号是按照选入时间排列的&#xff0c;与含金量无关&#xff0c;华为杯是23年选入的&#xff09; Kimi Chat: 全国…

攻防世界09cookie

9-cookie Cookie是保存在客户端的纯文本文件。比如txt文件。所谓的客户端就是我们自己的本地电脑。当我们使用自己的电脑通过浏览器进行访问网页的时候&#xff0c;服务器就会生成一个证书并返回给我的浏览器并写入我们的本地电脑。这个证书就是cookie。一般来说cookie都是服务…

数字孪生技术在设备故障检测中的应用

数字孪生技术在设备故障检测中的应用主要体现在以下几个方面&#xff0c;数字孪生技术在设备故障检测中的应用展现了其在智能制造和工业互联网领域的重要价值&#xff0c;通过实时监测、故障预测、诊断分析和预测性维护等手段&#xff0c;显著提升了设备管理的智能化水平。北京…

CAN终端电阻

目录 概述终端电阻的作用提高抗干扰能力确保快速进入隐性状态提高信号质量 为什么选120Ω 概述 CAN总线终端电阻&#xff0c;顾名思义就是加在总线末端的电阻。此电阻虽小&#xff0c;但在CAN总线通信中却有十分重要的作用。 终端电阻的作用 CAN总线终端电阻的作用有两个&…

轻松上手MYSQL:MYSQL初识(下)

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《MYSQL入门》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 轻松上手MYSQL&#xff1a;从零开始构建你的数据库世界 &#x1f680; &#x1f680;欢迎来到My…

office竟然可以直接PDF转Word?这个“锅”请wps来背!

WPS和Office都是非常出色的办公软件&#xff0c;它们都能够满足我们日常办公的需求。然而&#xff0c;作为一款国产办公软件&#xff0c;WPS在功能集成和操作上更加符合中国人的使用习惯&#xff0c;因此很多人选择使用WPS作为他们的办公软件&#xff0c;包括我自己。 然而&…

初识微服务:重塑软件开发的未来

引言 随着信息技术的飞速发展&#xff0c;软件系统的复杂性和规模不断攀升&#xff0c;传统的单体应用架构已经难以满足现代业务的灵活性和可扩展性需求。在这样的背景下&#xff0c;微服务架构应运而生&#xff0c;成为当前软件开发领域的一大热门话题。本文将深入探讨微服务架…

LeetCode 73.矩阵置零————2024 春招冲刺百题计划

给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 示例 2&#xff1a; 输入&#xff1a;matrix […

解决EasyPoi导入Excel获取不到第一列的问题

文章目录 1. 复现错误2. 分析错误2.1 导入的代码2.2 DictExcel实体类2.2 表头和标题 3. 解决问题 1. 复现错误 使用EasyPoi导入数据时&#xff0c;Excel表格如下图&#xff1a; 但在导入时&#xff0c;出现如下错误&#xff1a; name为英文名称&#xff0c;在第一列&#xff0c…

0-1 设计高质量数据可视化大屏

5 大指南塑造高阶可视化 可视化是个友好的媒介 理解数据是成为优秀媒介的关键 业务驱动下的设计策略 图扑设计的无限可能 创新思维让可视化更具价值 可视化是个友好的媒介 我们正处于一个数据泛滥的时代&#xff0c;随处可见数据的身影&#xff0c;更知其不可忽视的重要…

金三银四面试题(二十):单例模式知多少?

设计模式也是面试中的热门考题&#xff0c;基本这个部分都是问问你知不知道XXX设计模式&#xff0c;有什么用&#xff0c;优缺点&#xff0c;然后再现场手写一个demo。很多时候是和spring一起考的&#xff0c;问问你知不知道spring框架用了哪些设计模式。今天我们来先看看单例模…

免费SSL证书安全吗?和付费的有什么区别?

SSL&#xff08;安全套接层&#xff09;证书是一种数字证书&#xff0c;用于在Web服务器和浏览器之间建立加密链接&#xff0c;以保护在线交易的安全。这种技术可以防止数据被窃取或篡改&#xff0c;从而保护用户的隐私和安全。 免费SSL证书与付费SSL证书在安全性方面存在一定…

java的Spring XML和注解解析深入理解

正文 熟悉IOC体系结构 要学习Spring源码&#xff0c;我们首先得要找准入口&#xff0c;那这个入口怎么找呢&#xff1f;我们不妨先思考一下&#xff0c;在Spring项目启动时&#xff0c;Spring做了哪些事情。这里我以最原始的xml配置方式来分析&#xff0c;那么在项目启动时&a…

论文略读:SWE-bench: Can Language Models Resolve Real-world Github Issues?

iclr 2024 oral reviewer评分 5668 现有的语言模型&#xff08;LMs&#xff09;的基准测试已经饱和&#xff0c;无法捕捉到最先进的语言模型能做什么和不能做什么的前沿。 ——>要具有挑战性的基准测试论文引入了SWE-bench 在现实软件工程环境中评估语言模型的基准测试 ​​…

Spring Boot+Mybatis+DM数据库

达梦数据库(DM Database)是武汉达梦数据库股份有限公司研发的新一代大型通用关系型国产数据库&#xff0c;全面支持 SQL 标准和主流编程语言接口/开发框架。行列融合存储技术&#xff0c;在兼顾 OLAP 和 OLTP 的同时&#xff0c;满足 HTAP 混合应用场景。 在公司项目开发过程中…

E9:拦截流程系统管理员操作记录,流转记录不显示(ECODE)

效果&#xff1a; ecodeSDK.rewriteApiDataQueueSet({fn: (url, params, data) > {const { hash } window.location;if (!hash.startsWith(#/main/workflow/req)) return false; // 判断页面地址if (!ecCom.WeaTools.Base64) return false; // 完整组件库加载完成if (!W…

【RabbitMQ】RabbitMQ基础认识

文章目录 前言初识MQSpringAMQP如何首发消息&#xff1f;消费者交换机Fanout&#xff1a;广播Direct交换机Topic交换机声明队列和交换机 总结 前言 微服务一旦拆分&#xff0c;必然涉及到服务之间的相互调用&#xff0c;目前我们服务之间调用采用的都是基于OpenFeign的调用。这…

【五十一】【算法分析与设计】KMP 算法,KMP 算法的作用,KMP 算法流程,KMP 算法证明,KMP 算法代码

目录 KMP 算法的作用&#xff0c;解决的问题 KMP 算法的流程 Next 数组 KMP 算法正式过程 KMP 算法的证明过程 Next 数组的求法 Next 数组求法的证明过程 KMP 算法代码 结尾 KMP 算法的作用&#xff0c;解决的问题 1. 首先给你一个字符串 str&#xff0c;然后又给你…

酷开系统丨酷开科技打造P9系列智能投影,让智能化更进一步

近些年&#xff0c;随着科技的进步&#xff0c;家用投影仪已经成为家庭娱乐中不可或缺的一部分。尤其对年轻人来说&#xff0c;他们更喜欢在巨幕上看电影、玩游戏或听歌唱歌&#xff0c;投影仪在巨幕上的光影效果确实能带来更好的沉浸感体验&#xff0c;但这也是需要强大的系统…