• 如何创建 Qt 插件?


    如何创建 Qt 插件?

    简单三部曲

    1. 定义接口类或接口基类并使用 Q_DECLARE_INTERFACE 宏进行声明
    2. 所有的插件都需要继承该基类并继承 QObject(不带界面插件) or QWidget(带界面插件)
    3. 在插件类中添加 Q_PLUGIN_METADATA 导出元数据,使用 Q_INTERFACES 指定继承基类(该基类需要使用 Q_DECLARE_INTERFACE 声明过)

    如何生成?

    示例
    *.pro 文件内容如下

    # 插件依赖模块
    QT       += core gui widgets
    
    # 生成目标文件名称
    TARGET = FlowWidget
    TEMPLATE = lib
    CONFIG += plugin
    
    # 插件输出目录
    DESTDIR = $$[QT_INSTALL_PLUGINS]/generic
    
    DEFINES += QT_DEPRECATED_WARNINGS
    
    SOURCES += 
            flowWidget.cpp
    
    HEADERS += 
            flowWidget.h
    
    DISTFILES += FlowWidget.json 
    
    include($$PWD/interface/interface.pri)
    

    interface.pri 内容如下:

    SOURCES += 
    
    HEADERS += 
        $$PWD/flowInterface.h
    
    INCLUDEPATH += $$PWD
    

    纯接口类定义如下:

    #include <QtPlugin>
    class QImage;
    class QString;
    class QWidget;
    class FlowInterface
    {
    public:
        FlowInterface() {}
        virtual ~FlowInterface() {}
        virtual void process() = 0;
        /*!
            属性页
        */
        virtual QWidget *propertyPage() = 0;
    };
    
    #define FlowInterface_iid "com.xiongwei.cheung.FlowInterface"
    
    Q_DECLARE_INTERFACE(FlowInterface, FlowInterface_iid)
    

    注意:在插件类中我们需要实现接口中定义的纯虚函数

    插件定义分为带界面和不带界面两种,采用多重继承的方式分别继承 QWidget 或 QObject 即可.

    1. 带界面插件定义如下:
    class FlowWidget : public QWidget , FlowInterface
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(IID "com.xiongwei.cheung.FlowWidget" FILE "FlowWidget.json")
        Q_INTERFACES(FlowInterface)
    public:
        explicit FlowWidget(QWidget *parent = nullptr);
        void process();
        QWidget *propertyPage();
    signals:
    
    public slots:
    
    private:
    
    };
    
    FlowWidget::FlowWidget(QWidget *parent) : QWidget(parent)
    {
    
    }
    
    void FlowWidget::process()
    {
        // to do something
    }
    
    QWidget *FlowWidget::propertyPage()
    {
        return this;
    }
    

    FlowWidget.json 文件是可选的,可通过该文件实现密钥插件

    {
        "Keys" : [ "FlowWidget" ]
    }
    
    1. 不带界面插件定义如下:
    class FlowObject : public QObject , FlowInterface
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(IID "com.xiongwei.cheung.FlowObject")
        Q_INTERFACES(FlowInterface)
    public:
        explicit FlowObject(QObject *parent = nullptr);
        void process();
        QWidget *propertyPage();
    signals:
    
    public slots:
    
    private:
    
    };
    
    FlowObject::FlowObject(QObject *parent) : QObject(parent)
    {
    
    }
    
    void FlowObject::process()
    {
        // to do something
    }
    
    QWidget *FlowObject::propertyPage()
    {
        return nullptr;
    }
    

    如何使用?

    main.cpp 文件中添加插件加载路径

    QCoreApplication::applicationDirPath().append("generic");
    

    在工程文件中包含插件接口基类文件 flowInterface.h

    #include <QPluginLoader>
    #include "flowInterface.h"
    
    void load()
    {
        // 添加一个枚举目录所有动态库文件即可加载所有插件
        QPluginLoader pluginLoader("FlowWidget.dll");
        // 打印插件元数据,即 json 文件内容中的键值数据
        qDebug() << pluginLoader.metaData();
        // 加载该插件
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            // 转换成接口基类指针
            FlowInterface *p  = qobject_cast<FlowInterface *>(plugin);
            if (p){
                // 显示界面
                p->propertyPage()->show();
            }
    
        }
    }
    

    注意一个插件类中只能存在一个 Q_PLUGIN_METADATA 宏,使用该宏会导出 qt_plugin_instanceqt_plugin_query_metadata 俩个函数。
    显然如果使用 2 次 Q_PLUGIN_METADATA 宏会导致函数重定义.

    实际上如果向导出多个插件的可以使用 QGenericPlugin 的手法根据 keys and `` 创建不同的对象.

  • 相关阅读:
    lnmp环境搭建
    Git常用命令
    博客园写随笔环境搭建
    Win常用软件
    Docker环境搭建
    ESP-8266 RTOS 环境搭建
    查看Linux信息
    博客园markdown语法
    Java后台技术(TDDL)
    Java后台技术(Dubbo入门)
  • 原文地址:https://www.cnblogs.com/cheungxiongwei/p/11949841.html
Copyright © 2020-2023  润新知