Qt框架学习 --- CTK

这篇具有很好参考价值的文章主要介绍了Qt框架学习 --- CTK。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录



前言

随着开发的深入,CTK框架还是要关注一下。了解CTK还是有必要的。本篇文章主要描述CTK框架加载带界面的插件,集成到主界面的操作。


一、准备阶段

什么是CTK? CTK怎么编译?这些就不赘述了,提供几个参考博客即可。
环境:Qt5.15.2 + vs2019(Qt6放弃吧,目前为止编不了;mingw也放弃吧,目前虽然能编过去,但是运行起来就崩溃。当前时间2024.1.11)
编译参考:https://blog.csdn.net/Mr_robot_strange/article/details/128547331
ctk框架使用demo参考:https://github.com/Waleon/CTK-examples

本次demo就是从Waleon的一个模块更改的。

二、使用介绍

1.核心思想

ctk框架核心主要有2点:框架和插件。框架加载插件,之间的通讯使用事件或者信号槽。

2.源码

2.1.框架部分资源目录树

Qt框架学习 --- CTK,QT,插件CTK,qt,学习

2.2.框架部分源码

框架的核心就是框架和需要调用的服务类(一个纯虚类,同插件共用一个)

  • App.pro
QT += core gui widgets
TEMPLATE = app
CONFIG += console
TARGET = App
DESTDIR = $$OUT_PWD/../bin
include($$PWD/../CTK.pri)
SOURCES += \
    MainWindow.cpp \
    main.cpp
FORMS += \
    MainWindow.ui
HEADERS += \
    MainWindow.h
  • CTK.pri
# CTK 安装路径
CTK_INSTALL_PATH = $$PWD/../CTKInstall_vs
# CTK 插件相关库所在路径(例如:CTKCore.lib、CTKPluginFramework.lib)
CTK_LIB_PATH = $$CTK_INSTALL_PATH/lib/ctk-0.1
# CTK 插件相关头文件所在路径(例如:ctkPluginFramework.h)
CTK_INCLUDE_PATH = $$CTK_INSTALL_PATH/include/ctk-0.1
# CTK 插件相关头文件所在路径(主要因为用到了 service 相关东西)
CTK_INCLUDE_FRAMEWORK_PATH = $$PWD/../../../CTK-master/Libs/PluginFramework
LIBS += -L$$CTK_LIB_PATH -lCTKCore -lCTKPluginFramework
INCLUDEPATH += $$CTK_INCLUDE_PATH \
               $$CTK_INCLUDE_FRAMEWORK_PATH
  • MainWindow.h
 #ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void addWidget(QList<QWidget*> wigList);
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
  • MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::addWidget(QList<QWidget *> wigList)
{
    if (wigList.isEmpty()) { return; }
    for (auto wig : wigList) {
        ui->widget->layout()->addWidget(wig);
    }
}
  • main.cpp
#include <QCoreApplication>
#include <QApplication>
#include <QDirIterator>
#include <QtDebug>
#include <ctkPluginFrameworkFactory.h>
#include <ctkPluginFramework.h>
#include <ctkPluginException.h>
#include <ctkPluginContext.h>

#include "../Service/welcome_service.h"
#include "MainWindow.h"
int main(int argc, char *argv[])
{
    // QCoreApplication app(argc, argv);
    QApplication app(argc, argv);

    ctkPluginFrameworkFactory frameWorkFactory;
    QSharedPointer<ctkPluginFramework> framework = frameWorkFactory.getFramework();
    try {
        // 初始化并启动插件框架
        framework->init();
        framework->start();
        qDebug() << "CTK Plugin Framework start ...";
    } catch (const ctkPluginException &e) {
        qDebug() << "Failed to initialize the plugin framework: " << e.what();
        return -1;
    }
    qDebug() << "********************";
    // 获取插件上下文
    ctkPluginContext* context = framework->getPluginContext();
    // 获取插件所在位置
    QString path = QCoreApplication::applicationDirPath() + "/plugins";
    // 遍历路径下的所有插件
    QDirIterator itPlugin(path, QStringList() << "*.dll" << "*.so", QDir::Files);
    while (itPlugin.hasNext()) {
        QString strPlugin = itPlugin.next();
        try {
            // 安装插件
            QSharedPointer<ctkPlugin> plugin = context->installPlugin(QUrl::fromLocalFile(strPlugin));
            // 启动插件
            plugin->start(ctkPlugin::START_TRANSIENT);
            qDebug() << "Plugin start:" << QFileInfo(strPlugin).fileName();
        } catch (const ctkPluginException &e) {
            qDebug() << "Failed to start plugin" << e.what();
            return -1;
        }
    }
    qDebug() << "********************";
    // 1. 获取所有服务
    QList<ctkServiceReference> refs = context->getServiceReferences<WelcomeService>();
    foreach (ctkServiceReference ref, refs) {
        if (ref) {
            qDebug() << "Name:" << ref.getProperty("name").toString()
                     <<  "Service ranking:" << ref.getProperty(ctkPluginConstants::SERVICE_RANKING).toLongLong()
                      << "Service id:" << ref.getProperty(ctkPluginConstants::SERVICE_ID).toLongLong();
            WelcomeService* service = qobject_cast<WelcomeService *>(context->getService(ref));
            if (service != Q_NULLPTR)
                service->welcome();
        }
    }
    qDebug() << "********************";
    // 2. 使用过滤表达式,获取感兴趣的服务
    refs = context->getServiceReferences<WelcomeService>("(&(name=CTK))");
    foreach (ctkServiceReference ref, refs) {
        if (ref) {
            WelcomeService* service = qobject_cast<WelcomeService *>(context->getService(ref));
            if (service != Q_NULLPTR)
                service->welcome();
        }
    }
    qDebug() << "********************";
    // 3. 获取某一个服务(由 Service Ranking 和 Service ID 决定)
    ctkServiceReference ref = context->getServiceReference<WelcomeService>();
    if (ref) {
        WelcomeService* service = qobject_cast<WelcomeService *>(context->getService(ref));
        if (service != Q_NULLPTR)
            service->welcome();
    }
    QList<QWidget*> wigList;
    refs = context->getServiceReferences<WelcomeService>("(&(name=Qui))");
    foreach (ctkServiceReference ref, refs) {
        if (ref) {
            WelcomeService* service = qobject_cast<WelcomeService *>(context->getService(ref));
            if (service != Q_NULLPTR) {
                wigList << service->widget();
                wigList << service->widget();
            }
        }
    }
    MainWindow w;
    w.addWidget(wigList);
    w.show();
    return app.exec();
}
  • MainWindow.ui

Qt框架学习 --- CTK,QT,插件CTK,qt,学习

2.3.插件部分资源目录树

Qt框架学习 --- CTK,QT,插件CTK,qt,学习

2.4.插件部分源码

插件的核心就是实现类(实现一个纯虚类,框架只调用纯虚类的方法 )和激活类。就拿WelcomeQui举例吧

  • WelcomeQui.pro
QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17 plugin
TEMPLATE = lib
TARGET = WelcomeQui
DESTDIR = $$OUT_PWD/../../bin/plugins
include($$PWD/../../CTK.pri)
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
    MainWindow.cpp \
    WelcomeQuiActivator.cpp \
    WelcomeQuiImpl.cpp
HEADERS += \
    MainWindow.h \
    WelcomeQuiActivator.h \
    WelcomeQuiImpl.h
FORMS += \
    MainWindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
    Resource.qrc
  • MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

  • MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

  • WelcomeQuiActivator.h 激活类
#ifndef WELCOMEQUIACTIVATOR_H
#define WELCOMEQUIACTIVATOR_H

#include <QObject>
#include <ctkPluginActivator.h>

class WelcomeQuiImpl;

class WelcomeQuiActivator : public QObject, public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)
    Q_PLUGIN_METADATA(IID "WELCOME_QUI")

public:
    void start(ctkPluginContext* context);
    void stop(ctkPluginContext* context);
private:
    WelcomeQuiImpl *m_pImpl;
signals:
};
#endif // WELCOMEQUIACTIVATOR_H
  • WelcomeQuiActivator.cpp
#include "WelcomeQuiActivator.h"
#include "WelcomeQuiImpl.h"
#include <QDebug>

void WelcomeQuiActivator::start(ctkPluginContext* context)
{
    ctkDictionary properties;
    properties.insert(ctkPluginConstants::SERVICE_RANKING, 3);
    properties.insert("name", "Qui");

    m_pImpl = new WelcomeQuiImpl();
    context->registerService<WelcomeService>(m_pImpl, properties);
}

void WelcomeQuiActivator::stop(ctkPluginContext* context)
{
    Q_UNUSED(context)
    delete m_pImpl;
}

  • WelcomeQuiImpl.h 实现类
#ifndef WELCOMEQUIIMPL_H
#define WELCOMEQUIIMPL_H

#include <QObject>
#include "../../Service/welcome_service.h"

class MainWindow;

class WelcomeQuiImpl : public QObject, public WelcomeService
{
    Q_OBJECT
    Q_INTERFACES(WelcomeService)

public:
    explicit WelcomeQuiImpl(QObject *parent = nullptr);
    ~WelcomeQuiImpl();
    void welcome() override;
    QWidget *widget() override;

private:
    MainWindow *_mainwindow = nullptr;
signals:
};

#endif // WELCOMEQUIIMPL_H

  • WelcomeQuiImpl.cpp
#include "WelcomeQuiImpl.h"
#include "MainWindow.h"
#include <QDebug>
WelcomeQuiImpl::WelcomeQuiImpl(QObject *parent)
    : QObject{parent}
{}
WelcomeQuiImpl::~WelcomeQuiImpl()
{
    delete _mainwindow;
}
void WelcomeQuiImpl::welcome()
{
    qDebug() << "welcome Qui";
}
QWidget *WelcomeQuiImpl::widget()
{
    _mainwindow = new MainWindow;
    return _mainwindow;
}
  • MainWindow.ui

Qt框架学习 --- CTK,QT,插件CTK,qt,学习

  • MANIFEST.MF
Plugin-SymbolicName: Welcome.Qui
Plugin-ActivationPolicy: eager
Plugin-Category: Demos
Plugin-ContactAddress: https://github.com
Plugin-Description: A plugin for welcome Qui
Plugin-Name: WelcomeQui
Plugin-Vendor: shawn
Plugin-Version: 0.0.1

3.文件结构

框架源码目录和插件源码目录的位置。service里面放的是引入ctk库的pri文件,用qt5.15.2+vs2019编译好的ctk的库放在源码的同级目录。bin是生成的目录,里面是exe和plugins文件夹,plugins文件夹里面是编好的插件库dll

Qt框架学习 --- CTK,QT,插件CTK,qt,学习

4.运行效果

不加载插件的时候,效果是这样的

Qt框架学习 --- CTK,QT,插件CTK,qt,学习
Qt框架学习 --- CTK,QT,插件CTK,qt,学习

加载插件后,效果是这样的

Qt框架学习 --- CTK,QT,插件CTK,qt,学习
Qt框架学习 --- CTK,QT,插件CTK,qt,学习

UI插件的widget已经被嵌入主界面中了


总结

本demo完全参考博主一去二三里的开源代码实现。
参考:
https://blog.csdn.net/mr_robot_strange/category_11663281.html
https://github.com/Waleon/CTK-examples
https://www.cnblogs.com/judes/p/13285743.html
本篇文章对应demo地址:
https://download.csdn.net/download/yonug1107716573/88731039文章来源地址https://www.toymoban.com/news/detail-783104.html

到了这里,关于Qt框架学习 --- CTK的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QT Creator上位机学习(一)基本类别及主体框架解析

    之前也学习制作过串口上位机和利用Qchart完成数据的曲线显示等等,但大多只是对网上的程序进行拼接,这次又需要做一个上位机,打算好好学习记录一下。 可以创建多种项目: 1.Qt Widgets Application:支持桌面平台的GUI应用程序,C++。 2.Qt Console Application:无GUI界面,控制台应

    2024年02月12日
    浏览(43)
  • Qt学习_11_构建内嵌子界面与独立子界面的框架

    对于较大的Qt项目而言,弹出的 独立 子界面 与 根据菜单在主窗口内切换的 内嵌 子界面是我们所必须面对的问题。那么在项目框架对这两部分内容应该如何布局,才能让项目 更清爽 , 更规整 。是本文着重讨论的内容。下图给出我们的最终设计框架。 1.1.1 创建 首先介绍独

    2024年02月02日
    浏览(32)
  • 【QT学习】Graphics View框架(进阶篇)- 派生QGraphicsItem类创建自定义图元item

    📢欢迎各位读者:点赞 👍 收藏 ⭐留言 📝 📢博客主页:https://blog.csdn.net/qq_59134387😀 📢原创不易,转载请标明出处;如有错误,敬请指正批评!💦 📢我不去想是否能够成功,既然选择了远方,便只顾风雨兼程!✨    在上一篇《Graphics View框架(基础篇)- 图元、场景

    2023年04月25日
    浏览(32)
  • 在visual studio里配置Qt插件并运行Qt工程

        Qt插件,也叫qt-vsaddin,它以*.vsix后缀名结尾。visual studio简称为VS,从visual studio 2010版本开始,VS支持Qt框架的开发,Qt以插件方式集成到VS里。这里简述在visual studio 2019里配置Qt 5.14.2插件,并配置Qt环境、编译和运行Qt工程。     下载VS2019,官网地址: https://visualstudio.mi

    2024年02月07日
    浏览(52)
  • qt.qpa.plugin:找不到Qt平台插件“wayland“|| (下载插件)Ubuntu上解决方案

    相信大家也都知道这个地方应该做什么,当然是下载这个qt平台的插件wayland,但是很多人可能不知道怎么下载这个插件。 那么我现在要说的这个方法就是针对这种的。 完事儿了奥兄弟们。 看看效果 正常了奥。

    2024年02月10日
    浏览(49)
  • QT基础篇(16)QT5单元测试框架

    1.QTEstLib框架 QTestLib框架是一个用于软件测试的开源框架,是Qt工具套件的一部分。它提供了一组用于编写自动化测试和单元测试的类和函数。 QTestLib可以方便地为Qt应用程序编写单元测试,包括测试GUI和非GUI的代码。它提供了一系列断言和辅助函数,用于验证测试的预期结果

    2024年01月25日
    浏览(39)
  • Qt--QPlugin插件

    Qt–动态链接库一文中提到,动态方式加载dll只能加载 extern \\\"C“ 的导出函数,而无法加载类,因此可以使用Qt提供的插件来实现导出类的动态加载。 QPlugin是Qt插件框架的一部分,是一种轻量级的插件系统,用于在QT应用程序中动态加载和卸载功能模块,QPluginLoader类提供了对

    2024年02月13日
    浏览(23)
  • Qt QGenericPlugin插件使用案例

    Qt插件的编写,有两种方式,一种是直接通过自定义接口类Interface来实现,一种是通过QtCreator自带的插件模板来创建。 这里我们先来实现第二种。 功能为点击主界面的按钮,显示插件界面。(插件和开发库一样,什么都可以放进去,只不过就是封装成方便调用的模块) 首先

    2024年02月06日
    浏览(43)
  • C++ Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统(3) 保存表格数据

    对上两篇篇的工作C++ Qt框架开发| 基于Qt框架开发实时成绩显示排序系统(1)-CSDN博客和C++ Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统(2)折线图显示-CSDN博客继续优化,增加一个 保存按钮,用于保存成绩数据。 1)在ui界面添加一个按钮         将其命名为saveBtn。

    2024年02月19日
    浏览(41)
  • [QT编程系列-3]:C++图形用户界面编程,QT框架快速入门培训 - 2- QT程序的运行框架:HelloWorld、常见控件、对象树原理

    目录 2. QT程序的运行框架 2.1 Hello World程序框架 2.2 QT Designer初识 2.3 用QT Designer设计用户登录界 上述示例代码中,首先根据应用程序的需求使用 QCoreApplication 或 QApplication 定义 app 对象。如果你的应用程序需要图形界面,则使用 QApplication,否则使用 QCoreApplication。然后,你可以

    2024年02月15日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包