此内容为原创,转载请注明出处。
环境
Qt 5.12.7
window 10
Qt的插件种类很多,但有些插件的协议是GPL协议,例如QtCharts。如果项目中使用了这种插件的话,那么就必须要共享源码。
商业软件肯定是不能共享源码的,所以就只能自制插件了。
自制插件的方式有很多种,可以直接写qml文件,使用时导入qml文件就行。但如果插件的代码除了bug需要修改,那么所有使用这个qml文件的源码都需要修改,很不方便。
所以,就决定写一个可以import的插件,方便好用。也可以把插件共享出来给广大网友,而不用担心源码泄露。
这篇博客的源码,会在最尾处给出来。
第一步 新建一个扩展插件项目
扩展插件项目,新建项目>>Library>>Qt Quick 2 Extension Plugin。
我们新建一个名为 QMLPlugin 的项目。
接下来需要输入class-name和URI,我们把URI更改成MyPlugin,class-name先不要改,等跑通整个程序后再做调整。
然后一直点击下一步,直到完成,这个时候我们就能得到一个完整的插件扩展项目。
请注意,这里有一个叫做 qmldir 的文件,打开文件看看。
很简单的两句话,这个文件第二步有用。
第二步 构建插件扩展项目
插件扩展项目新建完成后,我们对项目进行构建,分别用debug和release进行构建。
这样就能够得到一个debug的QMLPlugind.dll文件,和release的QMLPlugin.dll文件。注意:如果是linux的话,应该是so文件。
我们在桌面新建一个文件夹 MyPlugin(当然也可以叫其他名字),把我们刚刚构建出来的QMLPlugind.dll和QMLPlugin.dll,还有第一步的qmldir文件,放入到MyPlugin文件夹中。
再将MyPlugin这个文件夹放到Qt安装目录的qml文件夹下面,一定要找准位置。这个文件夹下面还有许多其它的qml插件,比如说QtCharts等。
第三步 新建一个qml项目做测试
在第一步和第二步都做完的情况下,讲道理qml中就已经可以调用了,我们测试一下。
新建一个qml的qt项目。
新建完成后,我们什么都不要改,直接打开main.qml文件,import刚刚我们新做的插件。
还记得刚刚的qmldir文件吗,里面有两行代码。
module MyPlugin
plugin QMLPlugin
这个module 里面的MyPlugin就是我们要导入的对象。我们先导入试用,然后我再说为什么可以导入。
导入成功,程序没有报红也没有报错。
好,还记得我们新建插件扩展项目时,说先不要改动的class-name吗,那个就是可以在qml中调用的插件名 MyItem,试用一下看看。
还有智能提示,这说明我们成功了,写完整了看看。
不出意外,没有报错,编译运行也都是正常的。
第四步 讲解为什么可以导入
在第三步我们试用时已经成功了,那为什么可以做到呢。
打开我们之前新建的插件扩展项目QMLPlugin,里面有一个文件qmlplugin_plugin.cpp,打开它。
看到了吗,有这么一句代码:
qmlRegisterType<MyItem>(uri, 1, 0, "MyItem");
这个uri就是之前新建项目输入的URI,也是写入qmldir文件的module,也就是我们可以import导入的原因,版本为1.0。
代码最后的参数"MyItem",就是我们在qml中使用的插件名,也可以换个其它任何你喜欢的名字,但最好是要首字母大写。
第五步 创建一个自己的插件
在第四步讲了为什么可以使qml导入后,大家或许也猜到了,只要用qmlRegisterType注册一下其它的对象,那么qml不就可以调用了吗。
我们实验一下,假设我想自定义一个提示板,可以设置颜色、文字、背景等功能。
首先新建一个c++类,名为NoticeBoard。
因为是给qml调用,所以这个类需要继承QQuickItem,又因为需要用到画板Painter,所以继承QQuickPaintedItem类,记得勾选Add Q_OBJECT的选项,因为可能会用到信号。
新建类后,因为没有头函数,所以文件会报错,我们把.h和.cpp文件都补充完整。
注意:
记得要加上这一句话:Q_DISABLE_COPY(NoticeBoard),否则qml中会报红色。
因为是继承了QQuickPaintedItem类,所以一定要记得重写paint函数,否则编译会报错的。
#ifndef NOTICEBOARD_H
#define NOTICEBOARD_H
#include <QQuickPaintedItem>
class NoticeBoard : public QQuickPaintedItem
{
Q_OBJECT
Q_DISABLE_COPY(NoticeBoard)
public:
NoticeBoard(QQuickItem *parent = nullptr);
~NoticeBoard() override;
protected:
void paint(QPainter *painter) override;
};
#endif // NOTICEBOARD_H
#include "noticeboard.h"
NoticeBoard::NoticeBoard(QQuickItem *parent) : QQuickPaintedItem(parent)
{
}
NoticeBoard::~NoticeBoard()
{
}
void NoticeBoard::paint(QPainter *painter)
{
}
构建一下,没有报错了。如果还有再报错的话,建议把构建出来的文件全部删除后,重新构建。
修改一下qmlplugin_plugin.cpp,使得qml中能够调用到这个插件。
#include "qmlplugin_plugin.h"
#include "myitem.h"
#include "noticeboard.h"
#include <qqml.h>
void QMLPluginPlugin::registerTypes(const char *uri)
{
// @uri MyPlugin
qmlRegisterType<MyItem>(uri, 1, 0, "MyItem");
qmlRegisterType<NoticeBoard>(uri, 1, 0, "NoticeBoard");
}
再使用debug和release分别对项目进行构建,将构建出来的两个dll库放入qt安装目录下,我们在第二步做的MyPlugin文件夹下。
记得一定是qt安装目录下的MyPlugin文件夹,这一步后面就不再重复了,每当更改了这个插件的代码时,都需要将dll文件更新一下。
我们去测试项目中测试一下
完全是没有问题的,运行也是没有问题。
第五步 让自己创建的插件有可修改属性
第四步创建插件提示板成功了,但是这个提示板没有颜色也没有文字,一片空白,现在来修改一下,首先修改颜色,我们希望在qml中可以控制提示板的颜色color属性。
我们就在NoticeBoard中增加一个color属性,用Q_PROPERTY的功能使得qml可以使用。
我们修改一下noticeboard.h和noticeboard.cpp文件。
#ifndef NOTICEBOARD_H
#define NOTICEBOARD_H
#include <QQuickPaintedItem>
#include <QPainter>
class NoticeBoard : public QQuickPaintedItem
{
Q_OBJECT
Q_DISABLE_COPY(NoticeBoard)
Q_PROPERTY(QString color READ getColor WRITE setColor NOTIFY colorChanged)
public:
NoticeBoard(QQuickItem *parent = nullptr);
~NoticeBoard() override;
QString getColor() const;
void setColor(const QString &color);
protected:
void paint(QPainter *painter) override;
private:
QString color = "#FF0000";
signals:
void colorChanged();
};
#endif // NOTICEBOARD_H
#include "noticeboard.h"
NoticeBoard::NoticeBoard(QQuickItem *parent) : QQuickPaintedItem(parent)
{
}
NoticeBoard::~NoticeBoard()
{
}
QString NoticeBoard::getColor() const
{
return color;
}
void NoticeBoard::setColor(const QString &color)
{
this->color = color;
emit colorChanged();
}
void NoticeBoard::paint(QPainter *painter)
{
QBrush brush; //画刷。填充几何图形的调色板,由颜色和填充风格组成
brush.setColor(QColor(color));
brush.setStyle(Qt::SolidPattern);
QPen pen; //画笔。
pen.setColor(QColor(color));
//在画板上画一个跟画板同宽同高的矩形
painter->setPen(pen);
painter->setBrush(brush);
painter->drawRect(0, 0, this->width(), this->height());
}
我们去测试一下
因为我在.h文件中默认color为#FF0000红色,所以如果我不在qml中设置颜色的话,画板应该是默认红色的,运行一下看看。
确实是红色, 那么我们修改一下颜色值看看代码成功没有,给它一个淡黄绿。
是不是成功啦。那我们按照同样的方式,设置一下文字和文字的颜色。
棒不棒?还能给文字设置大小,粗体等等。
源码
https://github.com/MaoShengYu/QMLPlugin.git