Qt5.2文档翻译:如何创建Qt插件,How to Create Qt Plugins
•. 一个较高级别的应用编程接口,用于为Qt本身编写扩展:自定义的数据库驱动、图片格式、文本编解码器、自定义样式等等。
•.一个较低级别的应用编程接口,用于为Qt 程序编写扩展。
例如,如果 妳 想要编写一个自定义的 QStyle 子类 ,并且让其它的 Qt应用程序动态载入 它的话,则, 妳需要使用前面所说的较高级别的应用编程接口。
由于高级别的应用编程接口是构建于低级别的应用编程接口之上的,所以,某些注意事项对于两者是通用的。
如果妳想提供一些能够在Qt Designer 中使用的插件,则,阅读Qt Designer模块文档。
主题:
要编写一个用于扩展Qt 本身的插件呢,其做法就是,子类化适当的插件基类、实现若干个函数、以及添加一个宏。
有多个插件基类。通过继承而产生的插件,默认情况下会储存在标准插件目录的子目录中。如果插件不是放置在正确的目录中的,则,Qt不会寻找它们。
基类 |
目录名 |
键的大小写敏感性 |
accessiblebridge |
大小写敏感 |
|
accessible |
大小写敏感 |
|
QDecorationPlugin |
decorations |
大小写不敏感 |
QFontEnginePlugin |
fontengines |
大小写不敏感 |
iconengines |
大小写不敏感 |
|
imageformats |
大小写敏感 |
|
QInputContextPlugin |
inputmethods |
大小写不敏感 |
QKbdDriverPlugin |
kbddrivers |
大小写不敏感 |
QMouseDriverPlugin |
mousedrivers |
大小写不敏感 |
QScreenDriverPlugin |
gfxdrivers |
大小写不敏感 |
QScriptExtensionPlugin |
script |
大小写敏感 |
QSqlDriverPlugin |
sqldrivers |
大小写敏感 |
styles |
大小写不敏感 |
|
QTextCodecPlugin |
codecs |
大小写敏感 |
假设,妳有一个新的样式类,名为 MyStyle , 妳希望将它做成一个插件。 所需编写的代码是狠直观的, 以下是该类的定义( mystyleplugin.h ):
class MyStylePlugin : public QStylePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE mystyleplugin.json)
public:
QStyle *create(const QString &key);
};
确保 该类的实现代码是位于一个 .cpp 文件中的:
#include "mystyleplugin.h"
QStyle *MyStylePlugin::create(const QString &key)
{
if (key.toLower() == "mystyle")
return new MyStyle;
return 0;
}
(注意 , QStylePlugin 是大小写不敏感的, 在我们的 create() 代码中,使用 了该键的全小写版本; 大部分其它插件都是大小写敏感的。 )
另外 ,对于 大部分插件,都需要一个类似 mystyleplugin.json 的文件,其中包含 着描述了 该插件的元数据。对于样式插件 ,其中只是简单 地包含着 一个样式列表,其中 的样式都是可由 此插件创建的:
{ "Keys": [ "mystyleplugin" ] }
在该 json 文件中需要提供的信息的类型,取决于具体的插件,请阅读对应的类的文档,以了解要在该文件中包含的信息的细节。
对于数据库驱动、图片格式、文本编解码器以及大部分其它的插件类型,都不需要进行显式的对象创建工作。Qt会按照需要找到并且创建它们。样式是个例外,因为,妳可能想要在代码中显式地设置一个样式。要想应用一个样式,则使用这样的代码:
QApplication ::setStyle( QStyleFactory ::create("MyStyle"));
某个插件类,还要求实现一些额外的函数。参考具体类的文档,以了解,每种类型的插件中,需要覆盖的虚函数的细节。
样式插件示例 ,展示了 ,如何实现一个扩展了 QStylePlugin 基类的插件。
不仅仅是 Qt本身 , 妳所写的 Qt程序 也可以通过插件来扩展。 这就要求应用程序要使用 QPluginLoader 来检测及载入插件。 在那种上下文中,插件就可以提供任意的功能,而不仅局限于数据库驱动 、图片格式、文本编解码器、样式以及别的用于扩展Qt 功能的插件类型。
要想通过插件让一个应用程序变成可扩展的,需要按照以下步骤来进行:
1.定义一组用来与该插件通信的接口(只含有纯虚函数的类)。
2. 使用 Q_DECLARE_INTERFACE () 宏来向 Qt 的 元对象系统 告知 这个接口。
3. 在应用程序中使用 QPluginLoader 来载入插件。
4. 使用 qobject_cast () 来测试某个插件是否实现了指定的接口。
编写一个插件,要按照以下步骤进行:
1. 声明 一个插件类,它继承 QObject 以及那些该插件想要提供的接口。
2. 使用 Q_INTERFACES () 宏来向 Qt 的 元对象系统 告知 这些接口。
3. 使用 Q_PLUGIN_METADATA () 宏来导出这个插件。
4. 使用 一个适当的 .pro 文件来构建这个插件。
例如,以下是某个接口类的定义:
class FilterInterface
{
public:
virtual ~FilterInterface() {}
virtual QStringList filters() const = 0;
virtual QImage filterImage(const QString &filter, const QImage &image,
QWidget *parent) = 0;
};
以下是一个实现了那个接口的插件类的定义:
#include <QObject>
#include <QtPlugin>
#include <QStringList>
#include <QImage>
#include <plugandpaint/interfaces.h>
class ExtraFiltersPlugin : public QObject , public FilterInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json")
Q_INTERFACES(FilterInterface)
public:
QStringList filters() const;
QImage filterImage(const QString &filter, const QImage &image,
QWidget *parent);
};
即插即画 示例 的文档中 会详细说明此过程。另外 ,阅读 创建针对Qt Designer 的自定义部件 以了解更多 与Qt Designer 相关的信息。 妳还可以研究一下 回声插件示例 , 那是一个更简单的示例,展示了如何实现 一个能够扩展Qt 应用程序功能的插件。 请注意, 在载入插件之前,必须要有一个已经初始化的 QCoreApplication 存在。
Qt应用程序会自动地发现哪些插件是可用的,因为,插件都储存在标准的插件子目录中。正因为这一点,应用程序不需要写任何代码来专门寻找及载入插件,Qt会自动处理好这些鸟事的。
在开发过程中,插件 的目录是 QTDIR/plugins (其中 , QTDIR 是 Qt 的安装目录 ) ,每种类型 的插件都位于针对该类型的子目录中,例如 styles 。如果 妳希望妳的应用程序使用插件 , 而又 不想使用标准的插件路径的话,则, 让妳的安装过程 来 决定 妳想要用来保存插件 的路径,并且记录 下这个路径,例如使用 QSettings 来记录, 以便让应用程序在日后运行时能够读取到。日后 ,应用程序可以调用 QCoreApplication::addLibraryPath () ,并且传入这个路径, 这样,这个插件就可以被妳的应用程序 所用了。注意 ,路径 中最后一部分(例如 styles )是不可以变动的。
如果 妳想让插件成为可载入的,则,一种解决方法就是, 在应用程序目录下创建一个子目录,然后 将 该插件放置到那个子目录中。如果 妳想将Qt 自带的任何插件(位于 plugins 目录 中的那些东西 )与妳的应用程序一起发布的话,则, 妳必须 将 plugins 下的子目录复制到妳的应用程序根目录中放置插件的位置( 也就是说,不要包含 plugins 目录 )。
欲知更多关于部署 的信息,则阅读 部署Qt应用程序 和 部署插件 文档 。
常见并且最灵活的在应用程序中包含插件的方法就是,将它编译为一个单独传送的动态库,并且在运行时检测及载入它。
插件可与妳的应用程序静态链接起来。如果妳编译了静态版本的Qt,则,这是包含Qt 的预定义插件的唯一方法。使用静态插件,会使得部署过程更顺利,但是,缺点就是,如果插件有了新功能,则,必须完整地重新编译及重新发布应用程序才能够加上这些新功能。
以静态库形式编译时,Qt会提供以下静态插件:
插件名字 |
类型 |
说明 |
qtaccessiblewidgets |
可用性 |
Qt 部件的可用性 |
qgif |
图片格式 |
GIF |
qjpeg |
图片格式 |
JPEG |
qmng |
图片格式 |
MNG |
qico |
图片格式 |
ICO |
qsvg |
图片格式 |
SVG |
qtiff |
图片格式 |
TIFF |
qsqldb2 |
SQL驱动 |
IBM DB2 |
qsqlibase |
SQL驱动 |
Borland InterBase |
qsqlite |
SQL驱动 |
SQLite版本3 |
qsqlite2 |
SQL驱动 |
SQLite版本2 |
qsqlmysql |
SQL驱动 |
MySQL |
qsqloci |
SQL驱动 |
Oracle (OCI) |
qsqlodbc |
SQL驱动 |
开放数据库连接(ODBC) |
qsqlpsql |
SQL驱动 |
PostgreSQL |
qsqltds |
SQL驱动 |
Sybase适应性服务器(TDS) |
要想静态链接 到这些插件的话, 则, 妳需要使用 QTPLUGIN 来将必需 的插件添加 到项目中。 Q_IMPORT_PLUGIN () 宏也需要添加到应用程序代码中,但是qmake 会自动生成这些代码并且添加到妳的应用程序项目中。
在妳的应用程序的 .pro 文件 中, 妳需要加入以下内容:
QTPLUGIN += qjpeg \
qgif \
qkrcodecs
如果 妳不希望那些添加 到QTPLUGIN 的插件被自动链接,则, 从 CONFIG 变量中删除 import_plugins :
CONFIG -= import_plugins
还可以创建妳自己的静态插件,按照以下步骤进行即可:
1. 向妳的插件的 .pro 文件中加入 CONFIG += static 。
2. 在妳的应用程序代码中使用 Q_IMPORT_PLUGIN ()宏。
3. 在应用程序的 .pro 文件中,使用 LIBS 来将妳的应用程序与妳的插件链接起来。
阅读 即插即画 示例 和相关的 基本工具 插件 以了解关于如何实现这一点的细节。
注意 : 如果 妳不是使用 qmake 来构建妳的插件的话,则, 妳需要确保定义 了 QT_STATICPLUGIN 这个预编译宏。
在静态构建中,默认 的 Qt平台适配插件 会被自动添加到 QTPLUGIN 中。如果 妳想使用最小 化平台适配插件替换默认的平台适配插件的话,则, 向 CONFIG 中加入 qpa_minimal_plugin 。
CONFIG += qpa_minimal_plugin
如果 妳即不希望默认的QPA插件被自动链接,也不希望最小化的QPA 插件被链接,则, 从 CONFIG 中删除 import_qpa_plugin :
CONFIG -= import_qpa_plugin
部署插件 文档涵盖 了将插件与应用程序一起部署以及在出现问题时对插件进行调试的过程。
参考 QPluginLoader 、 QLibrary 和 即插即画示例 。
Your opinionsHxLauncher: Launch Android applications by voice commands