[Qt][工程构建] Qt插件技术(c++实现导出为qml组件)

前言:

首先搞明白qt中插件的概念:

插件:一个可在运行时加载的动态库

Qt中,使用QPluginLoader加载插件

既然插件是一个动态库,那么把它静态编译到可执行文件中也是允许的

对于使用插件的应用程序来说,Qt 插件就是一个 QObject,只不过这个QObject需要实现插件Interface

PluginDialog::staticInstances()可以获得当前应用程序已经加载的所有插件
由此,可以理解PluginDialog管理所有插件

Qt中的插件分为两种:

1)应用程序插件,即为库封装;  2)Qt Creator插件,即服务于IDE的插件。

这里只讨论第一种,即应用程序插件。

分类:

应用程序插件也分为几种:

1)由c++代码实现,QWidget系列的库(动态库或静态库),这类插件的使用即为库的使用,有头文件和库文件即可;

2)由c++代码实现,集成QQuickItem,导出为qml组件,提供qml使用的库(动态库或静态库),这类插件的使用有别于1),不需要头文件,但是需要qmldir文件替代头文件,qmldir文件用来告知使用者,当前库的import路径是什么吗,同时还需要提供一个plugins.qmltypes文件来告知使用者当前dll中有哪些可用的qml类型,但是这个plugins.qmltypes是可选的;

3)由qml代码实现,直接指定qml文件路径作为import地址,这种方法不需要任何工程辅助,这其实相当于qml的组件技术;

4)由qml代码实现,但是纳入到2)中的工程中,工程输出时,需要把qml文件名列入qmldir文件中,这样其module路径则和c++模块一致。

由c++代码实现,集成QQuickItem(对应第2类)

步骤1:创建插件工程

步骤2:指定module的uri和基础c++类名

步骤3:插件工程说明

pluginexample_plugin.h

#ifndef PLUGINEXAMPLE_PLUGIN_H
#define PLUGINEXAMPLE_PLUGIN_H

#include <QQmlExtensionPlugin>

 /* OBT -- 所有qml插件都要继承QQmlExtensionPlugin类 */
class PluginExamplePlugin : public QQmlExtensionPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)

public:
    /* OBT -- 重写此虚函数,此函数用来告知qml引擎当前插件的module uri */
    void registerTypes(const char *uri) override;
};

#endif // PLUGINEXAMPLE_PLUGIN_H

pluginexample_plugin.cpp

#include "pluginexample_plugin.h"
#include "obtitem.h"

#include <qqml.h>

void PluginExamplePlugin::registerTypes(const char *uri)
{
     /* OBT -- 注册qml类型 */
    // @uri ObtPlugin
    qmlRegisterType<ObtItem>(uri, 1, 0, "ObtItem"); //尖括号里的为c++类名,"ObtItem"为导出的qml类型
}

obtitem.h

#ifndef OBTITEM_H
#define OBTITEM_H

#include <QQuickItem>
#include <QRect>

/* OBT -- 插件内组件的具体实现 */
class ObtItem : public QQuickItem
{
    Q_OBJECT
    Q_DISABLE_COPY(ObtItem)

public:
    explicit ObtItem(QQuickItem *parent = nullptr);
    ~ObtItem() override;

};


#endif // OBTITEM_H

obtitem.cpp

#include "obtitem.h"

ObtItem::ObtItem(QQuickItem *parent):
    QQuickItem(parent)
{
    // By default, QQuickItem does not draw anything. If you subclass
    // QQuickItem to create a visual item, you will need to uncomment the
    // following line and re-implement updatePaintNode()

    // setFlag(ItemHasContents, true);
}

ObtItem::~ObtItem()
{
}

qmldir

module ObtPlugin			#模块名称 import时使用
plugin PluginExample		#插件文件名称 PluginExample.dll

步骤4:工程输出及使用

工程输出内容如下:

将输出拷贝到一个单独的目录下,同时把qmldir文件也放在一起:

Test.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import ObtPlugin 1.0            //模块路径uri


Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ObtItem{                    //导出的qml类型
        x:20
        y:20
        width: 100
        height: 100
    }
}

步骤5:测试

结果可以正常弹窗,此文旨在说明插件的制作和使用,因此没有对ObtItem做任何实现,故窗口是空白的。

qmlscene -I ./ Test.qml 中的 -I ./ 是在当前路径下查找插件,代码中有  import ObtPlugin 1.0 导入插件,所以就需要插件放在 Test.qml 同级路径下的 ObtPlugin 文件夹中 。见步骤4中的目录结构截图。

由qml代码实现(对应3/4类)

将qml文件放到 dll 和 qmldir同级路径下,再在qmldir中添加相应语句即可,比如有 MyRect.qml,则qmldir写为

module ObtPlugin			#模块名称 import时使用
plugin PluginExample		#插件文件名称 PluginExample.dll
MyRect 1.0 MyRect.qml 		#添加MyRect.qml文件为ObtPlugin模块管理范围内的组件,通过MyRect来进行调用

文件存放结构:

猜你喜欢

转载自blog.csdn.net/ykun089/article/details/107220265
今日推荐