一、源码目录: Qt\Examples\Qt-5.12.4\widgets\tools\plugandpaint
二、定义接口
class FilterInterface
{
public:
    virtual ~FilterInterface() {}
    virtual QStringList filters() const = 0;
    virtual QImage filterImage(const QString &filter, const QImage &image,
                               QWidget *parent) = 0;
};
QT_BEGIN_NAMESPACE //开始命名空间,不是必要
//定义id
#define FilterInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface/1.0"
//注册接口
Q_DECLARE_INTERFACE(FilterInterface, FilterInterface_iid)
QT_END_NAMESPACE
 
二、插件端:
分两种,动态库、静态库,只是 CONFIG += plugin static(static 有无区别)
实现接口
//定义实现,继承自插件接口,也可以多继承插件接口(也就是可以一个类当多种插件)
class ExtraFiltersPlugin : public QObject, public FilterInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json") //告诉MOC 导出该类
    Q_INTERFACES(FilterInterface) //告诉MOC 实现那些接口
public:
    QStringList filters() const override;
    QImage filterImage(const QString &filter, const QImage &image,
                       QWidget *parent) override;
}; 
三、应用端
对于 静态插件
首先需要使用 Q_IMPORT_PLUGIN(BasicToolsPlugin) 进行导入
加载 静态插件
 //因为使用 Q_IMPORT_PLUGIN 导入了,所以使用全局指针获取插件   
 const auto staticInstances = QPluginLoader::staticInstances();
 for (QObject *plugin : staticInstances)
     populateMenus(plugin);
//将插件转为目标接口
 auto iBrush = qobject_cast<BrushInterface *>(plugin); 
对于动态插件
    //输入插件目录
    const auto entryList = pluginsDir.entryList(QDir::Files);
    for (const QString &fileName : entryList) {
        QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); //根据绝对地址找插件加载
        QObject *plugin = loader.instance();
        if (plugin) {
            populateMenus(plugin);
            pluginFileNames += fileName;
        } 
 
 










