Qt插件开发_入门教程

news2024/11/24 19:21:25

文章目录

  • 前言
  • 插件的好处
  • 具体流程
    • 1. 第一,我们先创建一个主框架应用(**第一个工程**)
    • 2. GUI 设计 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f215270ccfac4e038e7261c4b4891ec1.png)
    • 3. 创建动态库项目(**第2个工程**)
    • 4. 给插件项目添加qt界面类
    • 5.在插件工程添加一个头文件
    • 6. 编辑上面新建的头文件
    • 7.编辑插件工程的头文件和cpp文件
    • 8.去掉插件工程的影子编译
    • 9.找到插件的文件路径
    • 10.将PluginInterface.h添加到主框架中
    • 11.把插件工程的dll文件也拷贝到主框架工程中![在这里插入图片描述](https://img-blog.csdnimg.cn/61bea6b54d2848a3a40a08887d3c8b6c.png)
    • 12. 打开主框架界面头文件
    • 13.mainwindow.cpp
  • 补充:这个博主我真的栓q,很多细节没有讲
    • 1. error: Undefined interface=>这个非常重要,在沟通插件工程与主框架工程的这个头文件中,必须加上这个!!!
    • 2. error: C2039: "qt_metacall"
    • 3.error: C2039: "staticMetaObject": 不是 "PluginInterface" 的成员
    • 4.error: C2338: qobject_cast requires the type to have a Q_OBJECT macro
    • 5.error: C2440: “static_cast”: 无法从“QObject *”转换为“T”
  • 效果
    • 运行
    • 点击
    • 代码结构
  • 代码地址
  • 教程

前言

qt插件我虽然没用过,但是最近看了很多有关三维软件的开发,都是用qt做的,其中就用到了qt插件开发,今天来圆一下梦 : 终于有时间来填一下这方面知识的坑了!

插件的好处

    1. 减少主程序体积和占用内存大小
    1. 按模块升级不会影响到其他
    1. 效率高和维护成本低

具体流程

我们需要创建两个工程

1. 第一,我们先创建一个主框架应用(第一个工程)

2. GUI 设计 在这里插入图片描述

3. 创建动态库项目(第2个工程)

文件->New Project->
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. 给插件项目添加qt界面类

在这里插入图片描述
在这里插入图片描述
加一个label:
在这里插入图片描述

5.在插件工程添加一个头文件

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

6. 编辑上面新建的头文件

在这里插入图片描述

#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H

#include <QWidget>

#define PluginInterfaceIID "com.szweebon.PluginInterface/1.0.0"
class PluginInterface{
public:
    virtual ~PluginInterface() = default;
    virtual QWidget *getWidget() = 0;
};

#endif // PLUGININTERFACE_H

7.编辑插件工程的头文件和cpp文件

在这里插入图片描述

#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H

#include <QWidget>

#define PluginInterfaceIID "com.szweebon.PluginInterface/1.0.0"


class PluginInterface{
public:
    virtual ~PluginInterface() = default;
    virtual QWidget *getWidget() = 0;
};

Q_DECLARE_INTERFACE(PluginInterface,PluginInterfaceIID)//此宏必须定义,否则外部程序会报错。

#endif // PLUGININTERFACE_H

在这里插入图片描述

#include "plugindemo.h"
#include "form.h"

PluginDemo::PluginDemo()
{
    mGenWidget = Q_NULLPTR;
}

PluginDemo::~PluginDemo()
{
    if(mGenWidget){
        mGenWidget->deleteLater();
    }
}

QWidget *PluginDemo::getWidget()
{
    if(!mGenWidget){
        mGenWidget = new Form;
    }
    return mGenWidget;
}

8.去掉插件工程的影子编译

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

9.找到插件的文件路径

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

10.将PluginInterface.h添加到主框架中

在这里插入图片描述

11.把插件工程的dll文件也拷贝到主框架工程中在这里插入图片描述

我发现主框架目录有两个位置都有可执行目录,
我直接两个全放了,如下:
在这里插入图片描述
在这里插入图片描述

12. 打开主框架界面头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPluginLoader>//插件加载类

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();

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

在这里插入图片描述

13.mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "PluginInterface.h"
#include <QDir>
#include <QMessageBox>

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

MainWindow::~MainWindow()
{
    if(loader.isLoaded())
    {
        loader.unload();
    }
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QDir dir("F:/QT_code/1study/tetsPlugIn/Debug/debug");
    //QDir dir(qApp->applicationDirPath());//加载当前运行目录
    qDebug("目录1:%s",dir.path().toUtf8().constData());
    loader.setFileName(dir.filePath("PluginDemo.dll"));//将加载器的目录加载进来
    qDebug("目录2:%s",dir.filePath("PluginDemo.dll").toUtf8().constData());
    if(!loader.load())
    {
        qDebug("Failed to load loader");
        QMessageBox::critical(this,"Tips",loader.errorString());
        return ;
    }
    //实例化
    QObject *plugin = loader.instance();
    qDebug() << __FUNCTION__ << loader.errorString();
    if(plugin==NULL)
    {
        qDebug("loader.instance() is null");
        return;
    }
    qDebug("Success1");
    PluginInterface *pi = qobject_cast<PluginInterface *>(plugin);
    if(pi)
    {
        QWidget * w = pi->getWidget();
        qDebug("Success2");
        if(w)
        {
            ui->tabWidget->addTab(w,"hello plugin");
            qDebug("Success3");
        }
        qDebug("Success4");
    }else{
        qDebug("pi is NULL");
    }
}



在这里插入图片描述

补充:这个博主我真的栓q,很多细节没有讲

1. error: Undefined interface=>这个非常重要,在沟通插件工程与主框架工程的这个头文件中,必须加上这个!!!

Q_DECLARE_INTERFACE(PluginInterface,PluginInterfaceIID)//此宏必须定义,否则外部程序会报错。
在这里插入图片描述

2. error: C2039: “qt_metacall”

3.error: C2039: “staticMetaObject”: 不是 “PluginInterface” 的成员

4.error: C2338: qobject_cast requires the type to have a Q_OBJECT macro

由于在使用qobject_cast时,类型没有使用Q_OBJECT宏定义导致的

5.error: C2440: “static_cast”: 无法从“QObject *”转换为“T”

还是PluginInterface *pi = qobject_cast<PluginInterface *>(loader.instance());报错
解决:PluginInterface 要继承QObject
在这里插入图片描述

效果

运行

在这里插入图片描述

点击

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

代码结构

在这里插入图片描述

代码地址

代码地址

教程

教程

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

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

相关文章

矩阵乘积的迹对矩阵求导

矩阵A、B乘积的迹对矩阵A求导 下面来证明。

从研发域到量产域的自动驾驶工具链探索与实践

导读 本文整理自 2023 年 9 月 5 日百度云智大会 - 智能汽车分论坛&#xff0c;百度智能云自动驾驶云研发高级经理徐鹏的主题演讲《从研发域到量产域的自动驾驶工具链探索与实践》。 全文中部段落附有演讲中 2 个产品演示视频的完整版&#xff0c;精彩不容错过。 (视频观看&…

原文远知行COO张力加盟逐际动力 自动驾驶进入视觉时代?

11月7日&#xff0c;通用足式机器人公司逐际动力LimX Dynamics官宣了两位核心成员的加入。原文远知行COO张力出任逐际动力联合创始人兼COO&#xff0c;香港大学长聘副教授潘佳博士为逐际动力首席科学家。 根据介绍&#xff0c;两位核心成员的加入&#xff0c;证明一家以技术驱…

SAP-MM-查找采购订单的创建和修改日期

在采购订单页面可以查看采购订单的修改和创建&#xff0c;但是有些内容不能完成看到 例如这个订单显示是用户唐创建&#xff0c;但是他不记得是什么时候创建的&#xff0c;怎么创建的&#xff1f; 点击菜单-环境-表头更改、项目更改&#xff0c;可以查看更改内容 通过这个表可…

【解密ChatGPT】:从过去到未来,揭示其发展与变革

&#x1f38a;专栏【ChatGPT】 &#x1f33a;每日一句&#xff1a;天行健,君子以自强不息,地势坤,君子以厚德载物 ⭐欢迎并且感谢大家指出我的问题 文章目录 一、ChatGPT的发展历程 二、ChatGPT的技术原理 三、ChatGPT的应用场景 四、ChatGPT的未来趋势 五、总结 引言:随着…

kubernetes集群编排——k8s存储(configmap,secrets)

configmap 字面值创建 kubectl create configmap my-config --from-literalkey1config1 --from-literalkey2config2kubectl get cmkubectl describe cm my-config 通过文件创建 kubectl create configmap my-config-2 --from-file/etc/resolv.confkubectl describe cm my-confi…

ROS学习笔记(5):ros_control

1.ros_control简介 ros_control - ROS Wiki ros_control是为ROS提供的机器人控制包&#xff0c;包含一系列控制器接口、传动装置接口、控制器工具箱等,有效帮助机器人应用功能包快速落地&#xff0c;提高开发效率。 2.ros_control框架 ros_control总体框架&#xff1a; 针对…

vue使用websocket与springboot通信

WebSocket是HTML5下一种新的协议&#xff0c;它实现了浏览器与服务器全双工通信&#xff0c;能更好的节省服务器资源和带宽并达到实时通讯的目的 在很多项目中&#xff0c;都要用到websocket&#xff0c;使得前端页面与后端页进行实时通信&#xff0c;例如&#xff0c;实时查询…

SCI论文公式快捷获取

文章目录 前言IEEE论文公式获取Elsevier论文公式获取Springer的论文公式获取Wiley出版社公式获取SAGE出版社论文公式获取Taylor & Francis Group出版社论文公式获取latex源码转矢量公式 前言 相信许多做科研的同学对于文献公式如何提取很是抓狂&#xff0c;尤其是做PPT时&…

HCIP---企业网的三层架构

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 一.园区网 概念&#xff1a; 园区网是指在园区内建立起来的互联网基础设施&#xff0c;包括网络设备、传输网络、网络管理系统等&#xff0c;其目的是为了方便企业和园区管理方在园区内进…

论文浅尝 | 基于对多条思维链的元推理实现智能问答

笔记整理&#xff1a;屠铭尘&#xff0c;浙江大学硕士&#xff0c;研究方向为知识图谱 链接&#xff1a;https://arxiv.org/abs/2304.13007 1. 动机 1.1 Chain of Thought的诞生 尽管大语言模型在许多自然语言处理任务上表现出色&#xff0c;但由于其本质是token by token的类似…

深度学习环境搭建入门环境搭建(pytorch版本)

从Python安装到深度学习环境搭建 1. Anaconda安装 python可以通过官网下载exe&#xff0c;这里提供的是使用anaconda创建多个虚拟 的python环境&#xff0c;使用Anaconda Prompt管理虚拟环境更方便。 官网地址&#xff1a;Free Download|Anaconda 下载到本地后双击此文…

Mall4cloud 微服务商城系统 2.0 发布

导读现在 jdk17 和 spring boot 以及 spring cloud alibaba 2022 的第三方依赖已经趋于成熟&#xff0c;所以 mall4cloud 也一把梭哈做了升级嗷。 本次更新重点&#xff1a; 系统由 jdk8 最低要求升级到 jdk17spring boot 由 2.7.x 升级到 3.1.xjavax 升级到 jakartaspring-cl…

Flink--简介

1、Apache Flink 是一个实时计算的框架和分布式处理引擎&#xff0c;用于在无边界喝有边界数据流上进行有状态的计算&#xff0c;并且能够在常见的集群上运行&#xff0c;并能以内存速度和任意规模进行计算。 有边界数据流&#xff1a;指的是有开始&#xff0c;也有结束&…

CCF ChinaSoft 2023 论坛巡礼 | NASAC青年软件创新奖论坛

2023年CCF中国软件大会&#xff08;CCF ChinaSoft 2023&#xff09;由CCF主办&#xff0c;CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办&#xff0c;将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…

gdal3.5.0升级及安装cmake

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 本文主要是将gdal旧版本v3.2.1升级到v3.5.0&#xff0c;解决升级过程中的问题。 一、…

智慧社区大屏:连接社区生活的数字桥梁

随着科技的不断发展&#xff0c;智慧社区已经不再只是未来的概念&#xff0c;它已经在我们的眼前悄然崭露头角。智慧社区是一种基于数字技术的社区管理和生活方式&#xff0c;旨在提高社区的安全性、便利性和生活质量。而在这个数字化的社区中&#xff0c;智慧社区大屏起到了连…

竞赛 深度学习疲劳检测 驾驶行为检测 - python opencv cnn

文章目录 0 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习加…

VMware17安装教程

1、双击安装包 2、等待进度条走满 3、点击下一步 4、点击我接受 下一步 5、修改安装目录 添加path路径 下一步 6、取消用户体验设置 下一步 7、点击下一步 8、 点击安装 9、等待进度条走满 10、点击许可证 输入秘钥 11、 点击输入秘钥 12、 点击完成 完成安装 此时已经完成了安…

Nat. Med. | 基于遗传学原发部位未知癌症的分类和治疗反应预测

今天为大家介绍的是来自Alexander Gusev团队的一篇论文。原发部位未知癌症&#xff08;Cancer of unknown primary&#xff0c;CUP&#xff09;是一种无法追溯到其原发部位的癌症&#xff0c;占所有癌症的3-5&#xff05;。CUP缺乏已建立的靶向治疗方法&#xff0c;导致普遍预后…