简介
插件是一种遵循一定规范的应用程序接口编写出来的程序,定位于开发实现应用软件平台不具备的功能的程序。
插件API
Qt提供了两种API用于创建插件:一种是高阶API,用于扩展Qt本身的功能,如自定义数据库驱动,图像格式,文本编码,自定义样式等;一种是低阶API,用于扩展Qt应用程序。
通过插件扩展应用程序功能
A、定义一个接口集(只有纯虚函数的类),用来与插件交流。
B、用宏Q_DECLARE_INTERFACE()将该接口告诉Qt元对象系统。
C、应用程序中用QPluginLoader来加载插件。
D、用宏qobject_cast()来判断一个插件是否实现了接口。
创建插件
A、声明插件类,插件类继承自QObject和插件实现的接口。
B、用宏Q_INTERFACES()将插件接口告诉Qt元对象系统。
C、用宏Q_EXPORT_PLUGIN2()导出插件类。
D、用适当的.pro文件构建插件。
今天本来准备在网上找一下,看到很多博客就弄一点,扣扣搜搜生怕我学会了,要么就是要下载。不啰嗦直接进入主题。
第一步 创建工程
创建工程,选择“Other Project”->“Subdirs Project”,填写工程名称为MyPluginDemo,选择保存目录。
第二步****创建应用工程
在PluginApp工程上右键选择“New Subproject”菜单项,选择创建一个GUI应用,工程名称为MainAPP。
ui 界面就当做一个小的计算器
第三步 : 插件接口创建
在MainApp应用增加一个接口CalInterface.h。
#ifndef CALINTERFACE_H
#define CALINTERFACE_H
#include <QString>
#include <QtPlugin>
/*
定义计算的接口类 里面的方法都是纯虚函数
*/
class CalInterface
{
public:
virtual ~CalInterface(){}
virtual bool check(QString type,int a,int b) = 0; //检验
virtual int cal(QString type,int a,int b)=0; //计算
};
//声明接口类 IID
#define CalInterface_iid "MyPlugins.CalInterface"
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(CalInterface,CalInterface_iid)
QT_END_NAMESPACE
#endif // CALINTERFACE_H
第四步 创建插件子工程
在MyPluginDemo工程上右键选择“New Subproject”菜单项,选择创建一个的Library的C++库。本质就是一个lib 库
类型选择Qt Plugin 名称为CalPlugin
第五步 接口实现类的创建
创建实现插件接口的实现类CalPluginClass由于基类没有是CalInterface 现在还没有导入所以选择还没有。后面可以更改
适当修改pro文件
第六步 接口类的实现
CalPluginClass 对接口类的实现
头文件
```cpp
#ifndef CALPLUGINCLASS_H
#define CALPLUGINCLASS_H
#include <QObject>
#include "calinterface.h"
class CalPluginClass : public QObject,public CalInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "MyPlugins.CalInterface") //插件的数据信息
Q_INTERFACES(CalInterface) //接口类
public:
CalPluginClass(QObject *parent = 0);
//重写方法
bool check(QString type,int a,int b) override; //检验
int cal(QString type,int a,int b) override; //计算
};
#endif // CALPLUGINCLASS_H
源文件
#include "calpluginclass.h"
#include "qmath.h"
CalPluginClass::CalPluginClass(QObject *parent) :
QObject(parent)
{
}
bool CalPluginClass::check(QString type, int a, int b)
{
bool ret;
Q_UNUSED(a);
//除法分母不可以为0
if(type=="除"){
if(b==0){
ret=false;
}else{
ret=true;
}
}else {
ret=true;
}
return ret;
}
int CalPluginClass::cal(QString type, int a, int b)
{
int sum;
if(type=="加"){
sum=a+b;
}else if(type=="减"){
sum=a-b;
}else if(type=="乘"){
sum=a*b;
}else{
sum=a/b;
}
return sum;
}
第七步 应用工程对插件的加载
mainwindow 头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "calinterface.h"
#include <QIntValidator>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
//加载插件
bool loadPlugin();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
CalInterface *m_interface;
};
#endif // MAINWINDOW_H
mainwindow 源文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDir>
#include <QPluginLoader>
#include <QApplication>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//验证器
QIntValidator *val=new QIntValidator(0,999,this);
ui->lineEdit->setValidator(val);
ui->lineEdit_2->setValidator(val);
if (!loadPlugin())
{
QMessageBox::information(this, "Error", "Could not load the plugin");
}
}
MainWindow::~MainWindow()
{
delete ui;
}
//判断插件的是否存在
bool MainWindow::loadPlugin()
{
bool ret = true;
//获取当前应用程序所在路径
QDir pluginsDir(qApp->applicationDirPath());
#if defined(Q_OS_WIN)
if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release"){
pluginsDir.cdUp();
pluginsDir.cdUp();
}
#elif defined(Q_OS_MAC)
if (pluginsDir.dirName() == "MacOS")
{
pluginsDir.cdUp();
pluginsDir.cdUp();
pluginsDir.cdUp();
}
#elif defined(Q_OS_LINUX)
pluginsDir.cdUp();
#endif
//切换到插件目录
pluginsDir.cd("plugins");
//遍历plugins目录下所有文件
foreach (QString fileName, pluginsDir.entryList(QDir::Files))
{
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader.instance();
if (plugin)
{
//插件名称
QString pluginName = plugin->metaObject()->className();
//对插件初始化
if(pluginName == "CalPluginClass")
{
m_interface = qobject_cast<CalInterface*>(plugin);
if (m_interface)
ret = true;
break;
}
else
{
ret = false;
}
}
}
return ret;
}
void MainWindow::on_pushButton_clicked()
{
int a=ui->lineEdit->text().trimmed().toInt();
int b=ui->lineEdit_2->text().trimmed().toInt();
QString type=ui->comboBox->currentText();
bool ret=m_interface->check(type,a,b);
if(ret){
int sum=m_interface->cal(type,a,b);
ui->label->setText(QString("%1").arg(sum));
}else{
ui->label->setText("除法分母不可以为零");
}
}
看都看完了 点个赞再走呗!!!!嘻嘻!!
运行结果