将项目模块化,每一个模块单独开发,模块的组成形成最终的主程序,
- 灵活
- 升级
- 下载
- 卸载
在现代软件开发中,灵活性和可扩展性是至关重要的。随着项目的发展,经常需要添加新的功能模块或界面,同时也需要考虑到方便的升级、下载和卸载这些模块。QT框架提供了QPluginLoader类,使得插件化开发变得十分简单。本文将介绍如何利用QT的QPluginLoader实现UI界面的插件化管理,每个子窗口都作为独立的DLL插件,实现灵活的功能扩展和管理。
首先,我们需要定义一个抽象的插件接口,以便统一管理各个插件的加载和调用 .
在.pro添加依赖库, 并删除自带的全部文件
QT += gui core widgets
TEMPLATE = lib
CONFIG += plugin
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# Default rules for deployment.
unix {
target.path = $$[QT_INSTALL_PLUGINS]/generic
}
!isEmpty(target.path): INSTALLS += target
新建 abstractplugin.h 抽象接口类, 带Ui 界面的插件接口
在这个接口中,定义了一个纯虚函数
object()
,用于返回插件所对应的QWidget对象。同时,利用Q_DECLARE_INTERFACE
宏声明了该接口,以便在后续插件加载时进行识别。
#ifndef ABSTRACTPLUGIN_H
#define ABSTRACTPLUGIN_H
#include <QObject>
class QWidget;
class AbstractPlugin {
public:
virtual ~AbstractPlugin() = default;
virtual QWidget *object() = 0;
};
// id 可以自己按照项目定义
#define AbstractInterface_iid "com.Plugin.AbstractPlugin"
//只有添加了这个宏之后,这个插件才能被QT识别。
Q_DECLARE_INTERFACE(AbstractPlugin, AbstractInterface_iid)
#endif //ABSTRACTPLUGIN_H
接下来,我们可以实现具体的插件。每个插件对应一个单独的DLL文件,通过继承抽象插件接口并实现其中的虚函数来完成插件的编写。下面是一个示例插件的实现 :
1:右击项目 新建ui界面
2:继承AbstractPlugin
实现抽象方法 object 返回自己。注意:这里是多列 每次调用会创建一个对象
3:添加一个用于描述插件信息的json文件
4:界面按照自己的需求写
5:点击编译生成dll
使用插件:
#include <QApplication>
#include "abstractplugin.h"// 抽象接口文件
#include <QPluginLoader>
#include<QWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPluginLoader loader("untitled.dll");
loader.load();
// 获取插件json文件信息
qDebug() << loader.metaData();
QObject *plugin = loader.instance();// 实例化
AbstractPlugin * pinterface = qobject_cast<AbstractPlugin *>(plugin);
QWidget *p = pinterface->object();// 调用实现的抽象方法,实列一个对象
QWidget *p1 = pinterface->object();
p->show();
p1->show();
return QApplication::exec();
}
运行结果:
打印出了json 中插件的信息
在目前的Qt 版本中,一旦加载了插件,卸载后插件一直未得到正真的释放,所以无法对插件文件进行删除,但是可以将插件文件改名。去除.dll的后缀 在程序每次运行的时候,自动删除不是.dll的文件.
插件的卸载。和删除插件dll 文件,
QStrin pluginPath = loader.fileName();// 获取插件所在的绝对路径位置
loader.unload();// 卸载插件
// 将插件改名,以.分割 不要后缀.dll
QFile::rename(pluginPath , pluginPath.split(".")[0]);