Qt QPlugin界面插件式开发Q_DECLARE_INTERFACE、Q_PLUGIN_METADATA和Q_INTERFACES
不搞那些什么粉丝可见,vip可见
直接上干货,先看效果!!!本文没介绍到位哈,其他的自行百度,我这个给懒人用的哈哈
1、首先正常创建qt项目1,然后添加.h文件编写一个纯虚类,这里为PluginTestInterface类具体如下:
#ifndef PLUGINTESTINTERFACE_H
#define PLUGINTESTINTERFACE_H
#include <QObject>
#include <QWidget>
//插件接口类,函数需要是纯虚函数
class PluginTestInterface
{
public:virtual ~PluginTestInterface(){}virtual void InitPage(QWidget *parent) = 0;virtual QWidget * GetWidget() = 0;virtual QString GetState() = 0;virtual void SlotUpdateText(QString text) = 0;
};//PluginTestInterface_iid需要全局唯一,唯一标识该接口;
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(PluginTestInterface, "PluginTestInterface_iid")
QT_END_NAMESPACE#endif // PLUGINTESTINTERFACE_H
2、如图创建一个项目2,该项目新建时选择【其他项目->Empty qmake Project】将PluginTestInterface.h文件拷贝1份放到该项目下,并添加到项目中。并且在项目Pro文件中添加以下代码:
#插件包含下面三个
QT += widgets uiplugin
TEMPLATE = lib
CONFIG += plugin
3、在项目2中新建c++类PluginTestInterface1 ,然后继承QObject和PluginTestInterface类,并在类中重写和添加内容,(注意:我添加的界面是为了测试插件能否使用界面)最终类头文件如下:
#ifndef PLUGINTESTINTERFACE1_H
#define PLUGINTESTINTERFACE1_H#include <QObject>
#include <QtPlugin>
#include "PluginTestInterface.h"
#include <QWidget>
#include <QPushButton>
#include <QTableWidget>
#include <QHBoxLayout>
//其他项目->empty qmake project
class PluginTestInterface1 :public QObject,public PluginTestInterface
{Q_OBJECT//插件需要添加下面几行,FILE非必要
Q_INTERFACES(PluginTestInterface)
//PluginTestInterface_iid是插件所实现的接口的唯一标识符,通常与 Q_DECLARE_INTERFACE 中的标识符一致;
// Q_PLUGIN_METADATA(IID "PluginTestInterface_iid")//注意编译前必需保存PluginTestInterface.json修改才会被编译进去Q_PLUGIN_METADATA(IID "PluginTestInterface_iid" FILE "PluginTestInterface.json")
public:explicit PluginTestInterface1();~PluginTestInterface1();void InitPage(QWidget *parent) override;QWidget * GetWidget() override;QString GetState() override;void SlotUpdateText(QString text) override;
private:QWidget *widget = nullptr;QPushButton* btn1 = nullptr;
signals:public slots:
};#endif // PLUGINTESTINTERFACE1_H
最终CPP文件如下:
#include "PluginTestInterface1.h"
PluginTestInterface1::PluginTestInterface1()
{
}PluginTestInterface1::~PluginTestInterface1()
{
}void PluginTestInterface1::InitPage(QWidget *parent)
{widget = new QWidget(parent);btn1 = new QPushButton(widget);QTableWidget* tab= new QTableWidget(widget);tab->setRowCount(8);tab->setColumnCount(8);QHBoxLayout *ly = new QHBoxLayout(widget);ly->addWidget(btn1);ly->addWidget(tab);
}QWidget *PluginTestInterface1::GetWidget()
{return widget;
}QString PluginTestInterface1::GetState()
{return "加载成功!";
}void PluginTestInterface1::SlotUpdateText(QString text)
{btn1->setText(text);
}
4、上面的PluginTestInterface.json文件是为了在插件dll中包含自己想要的信息,放在项目2的pro文件同目录下,这样在加载插件前可以先看这些信息,再决定是否加载插件。
Json文件内容如下(当然你想加什么就加什么哈,只是这个json文件需要手动写):
{
"code_version":"1.0",
"autor":"作者",
"infos":"该插件用于测试插件是否可以包含界面,并且界面与主程序可以相互包含。",
"last_changed_date":"2025-09-19"
}
5、在需要使用插件的地方,即项目1中,把项目2生成的PluginTestInterface1.dll放在项目1生成的exe同目录下,如下加载插件:
#include <QPluginLoader>
#include <QString>
#include <QDebug>
#include <QLineEdit>
#include <QJsonObject>
//加载插件页面
void MainWindow::on_pushButton_6_clicked()
{if(interface_){qDebug()<<"已加载过插件,向插件中插入控件";interface_->GetWidget()->layout()->addWidget(new QPushButton(interface_->GetWidget()));return;}QString a = qApp->applicationDirPath();qDebug()<<a;QString path = ".\\debug\\PluginTestInterface1.dll";QPluginLoader pluginLoader(path);QJsonObject metadata=pluginLoader.metaData();QJsonObject map = metadata.value("MetaData").toObject();qDebug()<<"code_version:"<<map.value("code_version").toString();qDebug()<<"autor:"<<map.value("autor").toString();qDebug()<<"infos:"<<map.value("infos").toString();qDebug()<<"last_changed_date:"<<map.value("last_changed_date").toString();//下面的代码才会加载if(pluginLoader.instance()){interface_ = qobject_cast<PluginTestInterface*>(pluginLoader.instance());if(interface_){QString aa = interface_->GetState();qDebug()<<aa;interface_->InitPage(ui->widget);ui->widget->layout()->addWidget(interface_->GetWidget());ui->lineEdit->setPlaceholderText("该输入完成时传递内容给插件按钮");}elseqDebug()<<"加载失败!";}
}
6、加载后就可以像普通类一样调用函数了,如
void MainWindow::on_lineEdit_editingFinished()
{if(interface_)interface_->SlotUpdateText(ui->lineEdit->text());
}