QWidget应用封装为qt插件,供其他qt应用调用

news/2025/1/1 23:56:50/

在之前的文章中,有介绍通过QProcess的方式启动QWidget应用,然后将其窗口嵌入到其他的qt应用中,作为子窗口使用.这篇文章主要介绍qt插件的方式将QWidget应用的窗口封装为插件,然后作为其他Qt应用中的子窗口使用. 

插件优点:

与主程序为同一个进程,免去了进程间繁琐的通信方式,在不同进程间通信时,需要有一套协议来保证数据的及时性及稳定性.比较繁琐,而插件的方式,通过插件接口文件来进行通信,在接口文件中定义API,

接口文件(定义为纯虚类)(主程序通过接口文件来访问该插件,插件通过继承该接口,重写所有纯虚函数)

#pragma once#include <QtPlugin>QT_BEGIN_NAMESPACE
class QString;
class QWidget;
QT_END_NAMESPACE//定义视觉检测接口
class InterfaceVisionMeasure
{
public:virtual ~InterfaceVisionMeasure() = default;/// <summary>/// 创建视觉窗口对象指针/// </summary>/// <param name="iLanguage">0为英文,1为中文</param>/// <param name="parent">父对象</param>/// <returns>窗口指针</returns>virtual void* CreatWindow(int iLanguage, QWidget* parent = nullptr) = 0;/// <summary>/// 获取对应序号轴编码器坐标/// </summary>/// <param name="GetAxisEncVal">回调对象</param>virtual void RegisterGetAxisEncVal(const std::function<void(int, double&)>& GetAxisEncVal) = 0;/// <summary>/// 获取对应序号轴规划位置坐标/// </summary>/// <param name="GetAxisPrfVal">回调对象</param>virtual void RegisterGetAxisPrfVal(const std::function<void(int, double&)>& GetAxisPrfVal) = 0;/// <summary>/// 获取内部变量的值/// </summary>/// <param name="GetVariableInVal">回调对象</param>virtual void RegisterGetVariableInVal(const std::function<void(int, double&)>& GetVariableInVal) = 0;/// <summary>/// 设置内部变量的值/// </summary>/// <param name="SetVariableInVal">回调对象</param>virtual void RegisterSetVariableInVal(const std::function<void(int, const double&)>& SetVariableInVal) = 0;/// <summary>/// 设置当前测量文件路径(测量文件)/// </summary>/// <param name="dir">测量文件路径</param>virtual void SetCurrentMeaureFile(const QString& dir) = 0;/// <summary>/// 开启测量/// </summary>/// <param name="indexMain">工序号</param>/// <param name="IndexSub">工序号中的子序号</param>virtual void StartMeasureProcess(int indexMain, int IndexSub) = 0;/// <summary>/// 测量结果返回到主程序/// </summary>/// <param name="MeasureResult">回调对象</param>virtual void RegisterMeasureResult(const std::function<void(const int&, const QStringList&, const QVector<double>&)>& MeasureResult) = 0;/// <summary>/// 创建测量文件(编辑文件)/// </summary>/// <param name="dir">创建路径</param>/// <returns>0为正常,非0为失败</returns>virtual int NewMeasureFile(const QString& dir)=0;/// <summary>/// 打开测量文件(编辑文件)/// </summary>/// <param name="dir">打开路径</param>/// <returns>0为正常,非0为失败</returns>virtual int OpenMeasureFile(const QString& dir) = 0;/// <summary>/// 另存为测量文件(编辑文件)/// </summary>/// <param name="srcDir">源文件路径</param>/// <param name="desDir">目标文件路径</param>/// <returns>0为正常,非0为失败</returns>virtual int SaveAsMeasureFile(const QString& srcDir, const QString& desDir) = 0;/// <summary>/// 设置当前显示页/// </summary>/// <param name="indexMain">对应工序页, -10为找中心,-11为对焦</param>/// <param name="indexSub">对应工序页中的第几页</param>/// <returns>0为成功, </returns>virtual int SetShowMeasurePage(int indexMain, int indexSub)=0;/// <summary>/// 获取当前测量工程工序列表(测量文件)/// </summary>/// <param name="listType">工序列表</param>/// <returns>0为成功</returns>virtual int GetCurMeasureProgram(QVector<int>& listType)=0;
};QT_BEGIN_NAMESPACE
#define Interface_VisionMeasure_IID "Demina.Nc.VisionMeasureInterface/1.0"
Q_DECLARE_INTERFACE(InterfaceVisionMeasure, Interface_VisionMeasure_IID)
QT_END_NAMESPACE

重写接口类:   h文件

#pragma once#include <QObject>
#include "InterfacesVisionMeasure.h"class qcDllVisionMeasure : public QObject, public InterfaceVisionMeasure
{Q_OBJECTQ_INTERFACES(InterfaceVisionMeasure)Q_PLUGIN_METADATA(IID Interface_VisionMeasure_IID FILE "DllVisionMeasure.json")
public:qcDllVisionMeasure(QObject* parent = nullptr);~qcDllVisionMeasure() override;/// <summary>/// 创建视觉窗口对象指针/// </summary>/// <param name="parent">父对象</param>/// <returns>窗口指针</returns>void* CreatWindow(int iLanguage, QWidget* parent = nullptr) override;/// <summary>/// 获取对应序号轴编码器坐标/// </summary>/// <param name="GetAxisEncVal">回调对象</param>void RegisterGetAxisEncVal(const std::function<void(int, double&)>& GetAxisEncVal) override;/// <summary>/// 获取对应序号轴规划位置坐标/// </summary>/// <param name="GetAxisPrfVal">回调对象</param>void RegisterGetAxisPrfVal(const std::function<void(int, double&)>& GetAxisPrfVal) override;/// <summary>/// 获取内部变量的值/// </summary>/// <param name="GetVariableInVal">回调对象</param>void RegisterGetVariableInVal(const std::function<void(int, double&)>& GetVariableInVal) override;//设置内部变量的值void RegisterSetVariableInVal(const std::function<void(int, const double&)>& SetVariableInVal) override;/// <summary>/// 设置当前测量文件路径/// </summary>/// <param name="dir">测量文件路径</param>void SetCurrentMeaureFile(const QString& dir) override;/// <summary>/// 开启测量/// </summary>/// <param name="indexMain">工序号</param>/// <param name="IndexSub">工序号中的子序号</param>void StartMeasureProcess(int indexMain, int IndexSub) override;/// <summary>/// 测量结果返回到主程序/// </summary>/// <param name="MeasureResult">回调对象</param>void RegisterMeasureResult(const std::function<void(const int&, const QStringList&, const QVector<double>&)>& MeasureResult) override;/// <summary>
/// 创建测量文件
/// </summary>
/// <param name="dir">创建路径</param>
/// <returns>0为正常,非0为失败</returns>int NewMeasureFile(const QString& dir) override;/// <summary>/// 打开测量文件/// </summary>/// <param name="dir">打开路径</param>/// <returns>0为正常,非0为失败</returns>int OpenMeasureFile(const QString& dir) override;/// <summary>/// 另存为测量文件/// </summary>/// <param name="srcDir">源文件路径</param>/// <param name="desDir">目标文件路径</param>/// <returns>0为正常,非0为失败</returns>int SaveAsMeasureFile(const QString& srcDir, const QString& desDir) override;/// <summary>/// 设置当前显示页/// </summary>/// <param name="indexMain">对应工序页, -10为找中心,-11为对焦</param>/// <param name="indexSub">对应工序页中的第几页</param>/// <returns>0为成功, </returns>int SetShowMeasurePage(int indexMain, int indexSub) override;/// <summary>/// 获取当前测量工程工序列表/// </summary>/// <param name="listType">工序列表</param>/// <returns>0为成功</returns>int GetCurMeasureProgram(QVector<int>& listType) override;
private://视觉界面对象指针void* m_pMainWnd{};
};

在实现cpp中,封装QWidget窗口,创建其实例

#include "stdafx.h"
#include "qcDllVisionMeasure.h"
#include "qwaMeasureToolsVM.h"qcDllVisionMeasure::qcDllVisionMeasure(QObject *parent)
:QObject(parent)
{}qcDllVisionMeasure::~qcDllVisionMeasure()
{}void* qcDllVisionMeasure::CreatWindow(int iLanguage, QWidget* parent)
{qwaMeasureToolsVM* widget = new qwaMeasureToolsVM(iLanguage,true,parent);m_pMainWnd =(void*) widget;return m_pMainWnd;
}//采用回调的方式实现,插件通过回调函数来获取,设置参数
//获取对应序号轴编码器坐标
void qcDllVisionMeasure::RegisterGetAxisEncVal(const std::function<void(int, double&)>& GetAxisEncVal)
{if (m_pMainWnd){((qwaMeasureToolsVM*)m_pMainWnd)->RegisterGetAxisEncVal(GetAxisEncVal);}
}//获取对应序号轴规划位置坐标
void qcDllVisionMeasure::RegisterGetAxisPrfVal(const std::function<void(int, double&)>& GetAxisPrfVal)
{}//获取内部变量的值
void qcDllVisionMeasure::RegisterGetVariableInVal(const std::function<void(int, double&)>& GetVariableInVal)
{if (m_pMainWnd){((qwaMeasureToolsVM*)m_pMainWnd)->RegisterGetVariableInVal(GetVariableInVal);}
}//设置内部变量的值
void qcDllVisionMeasure::RegisterSetVariableInVal(const std::function<void(int, const double&)>& SetVariableInVal) 
{if (m_pMainWnd){((qwaMeasureToolsVM*)m_pMainWnd)->RegisterSetVariableInVal(SetVariableInVal);}
}/// <summary>/// 设置当前测量文件路径/// </summary>/// <param name="dir">测量文件路径</param>
void qcDllVisionMeasure::SetCurrentMeaureFile(const QString& dir)
{if (m_pMainWnd){((qwaMeasureToolsVM*)m_pMainWnd)->SetCurrentMeaureFileByMainApp(dir);}
}/// <summary>
/// 开启测量
/// </summary>
/// <param name="indexMain">工序号</param>
/// <param name="IndexSub">工序号中的子序号</param>
void qcDllVisionMeasure::StartMeasureProcess(int indexMain, int IndexSub)
{if (m_pMainWnd){((qwaMeasureToolsVM*)m_pMainWnd)->StartMeasureProcessByMainApp(indexMain, IndexSub);}
}/// <summary>
/// 测量结果返回到主程序
/// </summary>
/// <param name="MeasureResult">回调对象</param>
void qcDllVisionMeasure::RegisterMeasureResult(const std::function<void(const int&, const QStringList&, const QVector<double>&)>& MeasureResult)
{if (m_pMainWnd){((qwaMeasureToolsVM*)m_pMainWnd)->RegisterMeasureResult(MeasureResult);}
}/// <summary>
/// 创建测量文件
/// </summary>
/// <param name="dir">创建路径</param>
/// <returns>0为正常,非0为失败</returns>
int qcDllVisionMeasure::NewMeasureFile(const QString& dir)
{if (m_pMainWnd){return ((qwaMeasureToolsVM*)m_pMainWnd)->NewMeasureFile(dir);}return -1;
}/// <summary>
/// 打开测量文件
/// </summary>
/// <param name="dir">打开路径</param>
/// <returns>0为正常,非0为失败</returns>
int qcDllVisionMeasure::OpenMeasureFile(const QString& dir) 
{if (m_pMainWnd){return ((qwaMeasureToolsVM*)m_pMainWnd)->OpenMeasureFile(dir);}return -1;
}/// <summary>
/// 另存为测量文件
/// </summary>
/// <param name="srcDir">源文件路径</param>
/// <param name="desDir">目标文件路径</param>
/// <returns>0为正常,非0为失败</returns>
int qcDllVisionMeasure::SaveAsMeasureFile(const QString& srcDir, const QString& desDir) 
{ if (m_pMainWnd){return ((qwaMeasureToolsVM*)m_pMainWnd)->SaveAsMeasureFile(srcDir, desDir);}return -1;
}/// <summary>
/// 设置当前显示页
/// </summary>
/// <param name="indexMain">对应工序页, -10为找中心,-11为对焦</param>
/// <param name="indexSub">对应工序页中的第几页</param>
/// <returns>0为成功, </returns>
int qcDllVisionMeasure::SetShowMeasurePage(int indexMain, int indexSub) 
{ if (m_pMainWnd){return ((qwaMeasureToolsVM*)m_pMainWnd)->SetShowMeasurePage(indexMain, indexSub);}return -1;
}/// <summary>
/// 获取当前测量工程工序列表
/// </summary>
/// <param name="listType">工序列表</param>
/// <returns>0为成功</returns>
int qcDllVisionMeasure::GetCurMeasureProgram(QVector<int>& listType) 
{ if (m_pMainWnd){return ((qwaMeasureToolsVM*)m_pMainWnd)->GetCurMeasureProgram(listType);}return -1;
}

 json接口描述json文件,放在头文件同目录

{"Type": ["BT150D"],"Name": "VisionMeasure","Description": "this is vision measure tools.","Version": "1.0.0","Vendor": "demina"
}

设置工程生成为从exe改为dll

qt插件功能启动

至此重新封装QWdiget结束, 等待生成的dll,将其复制到主程序的exe文件路径下即可.

在主程序中要做的工作,即通过接口文件 声明一个接口实例指针.

bool NcCoreQt::InitPluginVisionMeasure()
{QString dir = qApp->applicationDirPath();dir += "/VisionMeasure.dll";//视觉插件的dllm_pPluginLoaderVM = new QPluginLoader(dir, this);QObject* plugin = m_pPluginLoaderVM->instance();//qDebug() << pluginLoader.metaData();if (plugin) {m_pInterfaceVM = qobject_cast<InterfaceVisionMeasure*>(plugin);if (m_pInterfaceVM){ qInfo() << tr("Load vision measure interface successful");return true;}}else{qDebug() << m_pPluginLoaderVM->errorString();}return false;
}


http://www.ppmy.cn/news/1559469.html

相关文章

<数据集>风力发电机损伤识别数据集<目标检测>

数据集下载链接 &#xff1c;数据集&#xff1e;风力发电机损伤识别数据集&#xff1c;目标检测&#xff1e;https://download.csdn.net/download/qq_53332949/90187097数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;2527张 标注数量(xml文件个数)&#xff1a;252…

基于PREEvision的UML设计

众所周知&#xff0c;PREEvision是一款强大的电子电气架构协同开发及管理软件&#xff0c;可以很好地帮助架构工程师完成架构开发工作&#xff0c;其功能包括需求管理、定义功能逻辑、系统软件开发、网络设计、线束设计及整体工程的产品线管理和变形管理等。随着工程师们越来越…

PostgreSQL CRUD 操作指南

PostgreSQL CRUD 操作指南 连接数据库 -- 连接到特定数据库 psql -U postgres -d xianxia-- 列出所有数据库 \l-- 切换数据库 \c xianxia-- 列出所有表 \dt-- 查看表结构 \d table_name基本 CRUD 操作 CREATE&#xff08;创建&#xff09; -- 创建新表 CREATE TABLE users …

自定义 Celery的logging模块

为什么需要自定义 Celery 日志 默认的 Celery 日志配置虽然满足基本需求&#xff0c;但在以下情况下可能需要进行自定义&#xff1a; 支持日志滚动&#xff1a;原生celery不支持日志滚动。更详细的日志信息&#xff1a;需要包含更多上下文信息&#xff0c;以便更好地理解任务…

Redis 数据类型全解析:基础与进阶应用场景

前言&#xff1a;Redis 是一个高性能的内存数据库&#xff0c;支持多种数据类型&#xff0c;能够高效处理各种场景的数据存储和操作。 以下是Redis数据类型的数据结构及其应用场景的详细说明&#xff1a; 基础数据类型 1. 字符串 (String) 底层数据结构 Simple Dynamic Stri…

我的软件架构师——Java 职位面试经历。

最近,我参加了一家领先的服务型公司的软件架构师(Java)职位的面试。我在这里分享了一些面试官问我的问题。我只列出了与 Java 相关的问题,因为本文主要关注 Java。面试官问我有关 AWS、Docker、Kubernetes、Kafka、Elastic Search、SQL/NoSQL 和设计模式的问题。 ClassNotF…

数据可视化-16. 日历图

目录 1. 日历图的概念 2. 日历图的适用场景 2.1 事件或活动的频率分析 2.2 数据的时间周期性分析 2.3 异常值检测 2.4 绩效监控 3. 日历图的缺陷 3.1 粒度受限于天数 3.2 数据密度过高时候难以解读 3.3 难以比较多个数据集 3.4 周期性较长的数据不易展示 4. 日历图…

PDF书籍《手写调用链监控APM系统-Java版》第6章 链路的架构(Trace+TraceSegment+Span)

本人阅读了 Skywalking 的大部分核心代码&#xff0c;也了解了相关的文献&#xff0c;对此深有感悟&#xff0c;特此借助巨人的思想自己手动用JAVA语言实现了一个 “调用链监控APM” 系统。本书采用边讲解实现原理边编写代码的方式&#xff0c;看本书时一定要跟着敲代码。 作者…