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

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

插件优点:

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

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

cpp 复制代码
#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文件

cpp 复制代码
#pragma once

#include <QObject>
#include "InterfacesVisionMeasure.h"

class qcDllVisionMeasure : public QObject, public InterfaceVisionMeasure
{
    Q_OBJECT
        Q_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窗口,创建其实例

cpp 复制代码
#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文件,放在头文件同目录

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

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

将qt插件功能启动

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

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

cpp 复制代码
bool NcCoreQt::InitPluginVisionMeasure()
{
   
    QString dir = qApp->applicationDirPath();
 
    dir += "/VisionMeasure.dll";//视觉插件的dll

    m_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;
}
相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript