Qt基于CTK Plugin Framework搭建插件框架--事件监听

news2024/11/20 4:46:46

文章目录

  • 一、前言
  • 二、框架事件
  • 三、插件事件
  • 四、服务事件
  • 五、添加事件监听

一、前言

CTK一共有三种事件可以监听:

  • 框架事件
  • 插件事件
  • 服务事件

但是这些事件只有在变化时才能监听到,如果已经变化过后,进入一个稳定的状态,这时才去监听,那么是无法监听到的。


二、框架事件

针对整个框架的,相当于只有一个,因为框架只有一个,但是这里有个问题,就是监听这个事件是在框架初始化之后的,所以根本没法监听到框架事件的初始化,只能监听到结束的事件。类型有:

事件说明
FRAMEWORK_STARTED
PLUGIN_ERROR
PLUGIN_WARNING
PLUGIN_INFO
FRAMEWORK_STOPPED
FRAMEWORK_STOPPED_UPDATE
FRAMEWORK_WAIT_TIMEDOUT

三、插件事件

在安装、启动插件的过程中呈现的,主要就是插件的一个状态的变化。类型有:

事件说明
INSTALLED
RESOLVED
LAZY_ACTIVATION
STARTING
STARTED
STOPPING
STOPPED
UPDATED
UNRESOLVED
UNINSTALLED

四、服务事件

在创建、回收插件时的事情,主要体现在服务的注册和注销。类型有:

事件说明
REGISTERED
MODIFIED
MODIFIED_ENDMATCH
UNREGISTERING

五、添加事件监听

子项目【Application】中新增类EventListener

在这里插入图片描述

#ifndef EVENT_LISTENER_H
#define EVENT_LISTENER_H

#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 onFrameworkEvent(const ctkPluginFrameworkEvent& event);
    // 监听插件事件
    void onPluginEvent(const ctkPluginEvent& event);
    // 监听服务事件
    void onServiceEvent(const ctkServiceEvent& event);
};

#endif // EVENT_LISTENER_H

#include "event_listener.h"

EventListener::EventListener(QObject *parent)
    : QObject(parent)
{
}

EventListener::~EventListener()
{
}

// 监听框架事件
void EventListener::onFrameworkEvent(const ctkPluginFrameworkEvent& event)
{
    if (!event.isNull()) {
        QSharedPointer<ctkPlugin> plugin = event.getPlugin();
        qDebug() << "FrameworkEvent: [" << plugin->getSymbolicName() << "]" << event.getType() << event.getErrorString();
    } else {
        qDebug() << "The framework event is null";
    }
}

// 监听插件事件
void EventListener::onPluginEvent(const ctkPluginEvent& event)
{
    if (!event.isNull()) {
        QSharedPointer<ctkPlugin> plugin = event.getPlugin();
        qDebug() << "PluginEvent: [" << plugin->getSymbolicName() << "]" << event.getType();
    } else {
        qDebug() << "The plugin event is null";
    }
}

// 监听服务事件
void EventListener::onServiceEvent(const ctkServiceEvent &event)
{
    if (!event.isNull()) {
        ctkServiceReference ref = event.getServiceReference();
        QSharedPointer<ctkPlugin> plugin = ref.getPlugin();
        qDebug() << "ServiceEvent: [" << event.getType() << "]" << plugin->getSymbolicName() << ref.getUsingPlugins();
    } else {
        qDebug() << "The service event is null";
    }
}


【main.cpp】中调用事件监听类

#include "mainwindow.h"

#include <QApplication>

#include "ctkPluginFrameworkFactory.h"
#include "ctkPluginFramework.h"
#include "ctkPluginException.h"
#include "ctkPluginContext.h"
#include "ctkPluginFrameworkLauncher.h"
#include <QDebug>

#include "../HelloCTK/HelloService.h"
#include "event_listener.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setApplicationName("CTK_PluginFramework");//给框架创建名称,Linux下没有会报错

    // 获取插件所在位置
    // 在插件的搜索路径列表中添加一条路径
    ctkPluginFrameworkLauncher::addSearchPath("../CTK/lib/ctk-0.1/plugins");
    ctkPluginFrameworkLauncher::start("org.commontk.eventadmin");

    ctkPluginFrameworkFactory frameworkFactory;
    QSharedPointer<ctkPluginFramework> framework = frameworkFactory.getFramework();

    // 初始化并启动插件框架
    try {
        framework->init();
        framework->start();
        qDebug() << "======================================";
        qDebug() << "CTK plugin framework start...";
        qDebug() << "======================================";
    } catch (const ctkPluginException &e) {
        qDebug() << "CTK plugin framework init err: " << e.what();
        return -1;
    }

    // 获取插件服务的contex
    ctkPluginContext* pluginContext = framework->getPluginContext();

    // 事件监听
    EventListener listener;
    pluginContext->connectFrameworkListener(&listener, SLOT(onFrameworkEvent(ctkPluginFrameworkEvent)));
    pluginContext->connectPluginListener(&listener, SLOT(onPluginEvent(ctkPluginEvent)));
    // 过滤 ctkEventAdmin 服务
    // QString filter = QString("(%1=%2)").arg(ctkPluginConstants::OBJECTCLASS).arg("org.commontk.eventadmin");
    pluginContext->connectServiceListener(&listener, "onServiceEvent"); //, filter);

    //---------------------------------------------------------------------------------------------------------------------------------------
    //注册事件调用
    try {
        // 安装插件
        QString HelloCTK_dir = "C:/Qt_Pro/build-CTK_PluginFramework-CMake-Debug/HelloCTK/bin/plugins/HelloCTK.dll";
        QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(HelloCTK_dir));
        qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
        // 启动插件
        plugin->start(ctkPlugin::START_TRANSIENT);
        qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());

        //获取元数据
        QHash<QString, QString> headers = plugin->getHeaders();
        ctkVersion version = ctkVersion::parseVersion(headers.value(ctkPluginConstants::PLUGIN_VERSION));
        QString name = headers.value(ctkPluginConstants::PLUGIN_SYMBOLICNAME);
        QString number = headers.value("Plugin-Number");
        qDebug()<<"version: "<<version;
        qDebug()<<"name: "<<name;
        qDebug()<<"number: "<<number;


    } catch (const ctkPluginException &e) {
        qDebug() << QString("Failed install or run plugin: ") << e.what();
        return -2;
    }

    // 获取服务引用
    ctkServiceReference reference = pluginContext->getServiceReference<HelloService>();
    if (reference) {
        // 获取指定 ctkServiceReference 引用的服务对象
        //HelloService* service = qobject_cast<HelloService *>(pluginContext->getService(reference));
        HelloService* service = pluginContext->getService<HelloService>(reference);
        if (service != Q_NULLPTR) {
            // 调用服务
            service->sayHello();
        }
    }

    //---------------------------------------------------------------------------------------------------------------------------------------
    //类通信
    try {
        // 安装插件
        QString BlogEventHandler_Path = "C:/Qt_Pro/build-CTK_PluginFramework-CMake-Debug/BlogEventHandler/bin/plugins/BlogEventHandler.dll";
        QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(BlogEventHandler_Path));
        qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
        // 启动插件
        plugin->start(ctkPlugin::START_TRANSIENT);
        qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
    } catch (const ctkPluginException &e) {
        qDebug() << QString("Failed install or run plugin: ") << e.what();
        return -2;
    }

    try {
        // 安装插件
        QString BlogManager_Path = "C:/Qt_Pro/build-CTK_PluginFramework-CMake-Debug/BlogManager/bin/plugins/BlogManager.dll";
        QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(BlogManager_Path));
        qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
        // 启动插件
        plugin->start(ctkPlugin::START_TRANSIENT);
        qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
    } catch (const ctkPluginException &e) {
        qDebug() << QString("Failed install or run plugin: ") << e.what();
        return -2;
    }

    //---------------------------------------------------------------------------------------------------------------------------------------
    //信号槽通信-测试插件
    try {
        // 安装插件
        QString BlogEventHandlerUsingSlot_Path = "C:/Qt_Pro/build-CTK_PluginFramework-CMake-Debug/BlogEventHandlerUsingSlot/bin/plugins/BlogEventHandlerUsingSlot.dll";
        QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(BlogEventHandlerUsingSlot_Path));
        qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
        // 启动插件
        plugin->start(ctkPlugin::START_TRANSIENT);
        qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
    } catch (const ctkPluginException &e) {
        qDebug() << QString("Failed install or run plugin: ") << e.what();
        return -2;
    }

    try {
        // 安装插件
        QString BlogManagerUsingSignal_Path = "C:/Qt_Pro/build-CTK_PluginFramework-CMake-Debug/BlogManagerUsingSignal/bin/plugins/BlogManagerUsingSignal.dll";
        QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(BlogManagerUsingSignal_Path));
        qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
        // 启动插件
        plugin->start(ctkPlugin::START_TRANSIENT);
        qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
    } catch (const ctkPluginException &e) {
        qDebug() << QString("Failed install or run plugin: ") << e.what();
        return -2;
    }

    //---------------------------------------------------------------------------------------------------------------------------------------
    //CTK服务工厂
//    try {
//        // 安装插件
//        QString Hello_Path = "C:/Qt_Pro/build-CTK_PluginFramework-CMake-Debug/Hello/bin/plugins/Hello.dll";
//        QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(Hello_Path));
//        qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
//        // 启动插件
//        plugin->start(ctkPlugin::START_TRANSIENT);
//        qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
//    } catch (const ctkPluginException &e) {
//        qDebug() << QString("Failed install or run plugin: ") << e.what();
//        return -2;
//    }

//    // 获取服务引用
//    ctkServiceReference reference = pluginContext->getServiceReference<HelloService>();
//    if (reference) {
//        // 获取指定 ctkServiceReference 引用的服务对象
//        //HelloService* service = qobject_cast<HelloService *>(pluginContext->getService(reference));
//        HelloService* service = pluginContext->getService<HelloService>(reference);
//        if (service != Q_NULLPTR) {
//            // 调用服务
//            service->sayHello();
//        }
//    }

    // 停止插件
    //ctkPluginFrameworkLauncher::stop();

    //---------------------------------------------------------------------------------------------------------------------------------------

    MainWindow w;
    w.show();

    return a.exec();
}


在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Android Studio实现一个新闻APP系统源码,仿网易,搜狐等新闻客户端,本科毕业设计必备项目

DavidTGNewsProject ##【Android】最新主流新闻app功能实现。仿网易,搜狐等新闻客户端 完整代码下载地址&#xff1a;Android Studio实现一个新闻APP系统源码 先给大家看一下效果图&#xff1a; 这个项目总体来说虽然不是特别难&#xff0c;但是确实非常常用的功能。是业余时间…

wordcloud | 词云 in python

wordcloud | 词云&#x1f928;wordcloud | 词云&#x1fae1;词云是啥&#x1f636;‍&#x1f32b;️词云的历史&#x1f914;安装 wordcloud 包&#x1f60e;官方文档&#x1f923;一个最简单的例子&#x1f44d;运行结果&#x1f60a;感谢&#x1f928;wordcloud | 词云 赢…

Vue中v-for不要和v-if一起使用

在Vue2中v-for和v-if一起使用时会报错&#xff1a;The xxx variable inside v-for directive should be replaced with a computed property that returns filtered array instead. You should not mix v-for with v-if原因&#xff1a;Vue2中当 v-if 与 v-for 一起使用时&…

4张图搞懂Salesforce的认证体系(附新手考证攻略)

Salesforce认证计划概述最近这一两年&#xff0c;Salesforce的Trailhead和认证太热门了&#xff0c;小伙伴们前赴后继地刷Badge拿认证&#xff0c;可以考的认证也随着产品家族的增加而增加&#xff0c;从十几年前的几个认证&#xff0c;增长到现在的40多个认证。与其他应用平台…

2023年自学网络安全珍藏版路线,高效入门

前言 【一一帮助安全学习一一】 ①网络安全学习路线 ②20份渗透测试电子书 ③安全攻防357页笔记 ④50份安全攻防面试指南 ⑤安全红队渗透工具包 ⑥网络安全必备书籍 ⑦100个漏洞实战案例 ⑧安全大厂内部视频资源 ⑨历年CTF夺旗赛题解析 01 什么是网络安全 网络安全可以基于攻击…

Seq2Seq增加attention机制的原理说明

以中文翻译为英文为例讲解seq2seq的原理&#xff0c;以及增加attention机制之后的seq2seq优化版本。 文本参考: Pytorch实现Seq2Seq&#xff08;Attention&#xff09;字符级机器翻译_pytorch seq2seq_孤独腹地的博客-CSDN博客 https://github.com/datawhalechina/learn-nlp…

Dbeaver连接ES问题一站解决

前言 最近几天一直做ES的TPS测试&#xff0c;每次看数据ES的数据都在嫌麻烦&#xff08;在postman指定索引通过url请求查看数据&#xff09;。最后决定还是整整Dbeaver连接ES。 一、当前境况 1、ES版本比较老&#xff0c;还是6.4.2的 2、Dbeaver直接连接已经提示支持8.x版本 3…

【自学Python】Python格式化输出

Python格式化输出 Python格式化输出教程 在 Python 中&#xff0c;print() 函数用于打印相应的信息到终端控制台&#xff0c;同时我们还可以通过 print() 函数的 % 占位符&#xff0c;来对输出进行格式化&#xff0c;即按照我们指定的格式进行输出。 Python格式化输出占位符…

灵能传输(思维 贪心)

题目如下&#xff1a; 思路 or 题解 如果我们可以发现前缀和&#xff0c;对于这个题有特殊的性质&#xff0c;这个题就不能做出来了&#xff0c;不然你会想我一样卡好长时间&#xff0c;从不知所措。 ai1ai,ai−1ai,ai−2aia_{i1}a_i,a_{i−1}a_i,a_i−2a_iai1​ai​,ai−1​a…

html 获取视频文件的宽高尺寸,怎么获取视频的宽度-解决方案

html代码 <video id"video" loop preload"auto" autoplay><source src"1.mp4" type"video/mp4">您的浏览器不支持Video标签。 </video> js代码 var videodocument.querySelector("#video");//当前视频…

Unity 之 资源加载 -- 可寻址系统使用介绍 -- 入门(三)

可寻址系统设置面板使用介绍介绍 -- 入门&#xff08;三&#xff09;一&#xff0c;可寻址系统目录介绍二&#xff0c;可寻址系统面板介绍2.1 Groups - 资源组2.2 Settings - 设置2.3 Profiles - 配置文件2.4 Event Viewer - 事件查看器2.5 Analyze - 分析工具2.6 Hosting - 托…

springAOP的注解使用

注解使用导入依赖常用注解&#xff1a;注意&#xff0c;给测试类起名字的时候千万不要定义成Test&#xff0c;测试的方法不可以有参数&#xff0c;不可以有返回值在使用注解的时候&#xff0c;还需要告诉spring应该从哪个包开始扫描,一般在定义的时候都写上相同包的路径需要导入…

GitLab安装到实战

简介 关于gitlab的入门与实战&#xff0c;这里使用的是docker安装。2核4g的话不太行。 安装 由于这里我是学习环境,所以买的是抢占式&#xff0c;配置也不是很高。 购买服务器示例 Docker安装步骤 1.安装docker yum install -y docker 2.启动docker systemctl start doc…

【JavaEE】进程和线程

目录 1. 进程 1.1 PCB 1.1.1. PID 1.1.2. 内存指针 1.1.3. 文件描述符表 1.1.4.进程调度相关的属性 1.2 进程的虚拟地址空间 1.3 进程间的通信 2. 线程 2.1 线程与进程之间的联系 2.2 多线程与多进程 1. 进程 在了解线程之前&#xff0c;我们首先要了解进程&…

RHCE学习笔记-253-3

system monitoring Introduction to system monitoring security breaches or system malfunctions can be detected with regular system monitoring system monitoring includes: file system monitoring log file analysis process monitoring file system analysis 如果定期…

谷粒商城-基础篇-Day08-调试会员等级相关接口

在P83级中&#xff0c;点击发布商品时没有出现请求 则需要解决 PubSub is not definded这个问题 PubSub是用来检测选择分类的值变动的。 选择分类值变动&#xff0c;会请求后台接口&#xff0c;动态更新选择品牌的选项。 安装依赖 npm install --save pubsub-js&#xff08…

算法队伍的搭建

&#x1f31e;欢迎来到数据结构的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f64f;作者水平很有限&#xff0c;如果发现错误&#xff…

网络安全必备1000道面试题集锦(附答案)

前言 以下为网络安全各个方向涉及的面试题&#xff0c;星数越多代表问题出现的几率越大&#xff0c;祝各位都能找到满意的工作。 注&#xff1a;本套面试题&#xff0c;已整理成pdf文档&#xff0c;但内容还在持续更新中&#xff0c;因为无论如何都不可能覆盖所有的面试问题&a…

使用ResNet18实现CIFAR10数据集的训练

如果对你有用的话&#xff0c;希望能够点赞支持一下&#xff0c;这样我就能有更多的动力更新更多的学习笔记了。&#x1f604;&#x1f604; 使用ResNet进行CIFAR-10数据集进行测试&#xff0c;这里使用的是将CIFAR-10数据集的分辨率扩大到32X32&#xff0c;因为算力相关的…

Git使用详解(图文+代码):基础内容

基础内容前言版本控制本地版本控制系统集中化版本控制系统分布式控制系统Git使用详解Git基础理解Git基础指令取得项目的Git仓库记录每次更新的仓库检查当前文件状态跟踪文件暂存已修改文件忽略某些文件查看已暂存和未暂存的更新提交更新跳过使用暂存区域移除文件远程操作的使用…