如何創建 Qt 插件

Qt 為創建插件提供瞭 2 個 API:

  • A higher-level API for writing extensions to Qt itself: custom database drivers, image formats, text codecs, custom styles, etc.
  • A lower-level API for extending Qt applications.

例如:若想要編寫自定義 QStyle 子類並讓 Qt 應用程序動態加載它,將使用更高級 API。

由於更高級 API 建立在更低級 API 之上,因此有一些問題是兩者公共的。

If you want to provide plugins for use with Qt Designer ,見 QtDesigner 模塊文檔編製。

話題:

The Higher-Level API: Writing Qt Extensions

編寫擴展 Qt 本身的插件是通過子類化適當插件基類、實現一些函數、及添加宏達成的。

There are several plugin base classes. Derived plugins are stored by default in sub-directories of the standard plugin directory. Qt will not find plugins if they are not stored in the right directory.

基類 目錄名 鍵區分大小寫
QAccessibleBridgePlugin accessiblebridge 區分大小寫
QAccessiblePlugin accessible 區分大小寫
QDecorationPlugin decorations 不區分大小寫
QFontEnginePlugin fontengines 不區分大小寫
QIconEnginePlugin iconengines 不區分大小寫
QImageIOPlugin imageformats 區分大小寫
QInputContextPlugin inputmethods 區分大小寫
QKbdDriverPlugin kbddrivers 不區分大小寫
QMouseDriverPlugin mousedrivers 不區分大小寫
QScreenDriverPlugin gfxdrivers 不區分大小寫
QScriptExtensionPlugin script 區分大小寫
QSqlDriverPlugin sqldrivers 區分大小寫
QStylePlugin styles 不區分大小寫
QTextCodecPlugin codecs 區分大小寫

Suppose that you have a new style class called MyStyle that you want to make available as a plugin. The required code is straightforward, here is the class definition ( mystyleplugin.h ):

class MyStylePlugin : public QStylePlugin
{
public:
    QStringList keys() const;
    QStyle *create(const QString &key);
};
					

確保類實現位於 .cpp file (including the class definition):

#include "mystyleplugin.h"
QStringList MyStylePlugin::keys() const
{
    return QStringList() << "MyStyle";
}
QStyle *MyStylePlugin::create(const QString &key)
{
    if (key.toLower() == "mystyle")
        return new MyStyle;
    return 0;
}
Q_EXPORT_PLUGIN2(pnp_mystyleplugin, MyStylePlugin)
					

(注意, QStylePlugin is case insensitive, and the lower-case version of the key is used in our create() 實現;其它大多數插件區分大小寫。)

對於數據庫驅動程序、圖像格式、文本編解碼器及大多數其它插件類型,明確創建對象不是必需的。Qt 將根據需要查找並創建它們。樣式例外,由於可能想要在代碼中明確設置樣式。要應用樣式,使用代碼像這樣:

QApplication::setStyle(QStyleFactory::create("MyStyle"));
					

某些插件類要求實現其它功能。見類文檔編製,瞭解各插件類型必須重實現的虛函數的有關細節。

The 樣式插件範例 shows如何實現插件以擴展 QStylePlugin 基類。

The Lower-Level API: Extending Qt Applications

不隻 Qt 本身,Qt 應用程序還可以被擴展透過插件。這要求應用程序檢測並加載插件,使用 QPluginLoader 。在這種情況下,插件可以提供任意功能,不限於數據庫驅動程序、圖像格式、文本編解碼器、樣式及擴展 Qt 功能的其它類型插件。

透過插件使應用程序可擴展,涉及以下步驟:

  1. 定義一組用於對話插件的接口 (僅具有純虛函數的類)。
  2. 使用 Q_DECLARE_INTERFACE () 宏告訴 Qt 的 元對象係統 關於接口。
  3. 使用 QPluginLoader 在應用程序中加載插件。
  4. 使用 qobject_cast () 測試插件是否有實現給定接口。

編寫插件涉及這些步驟:

  1. 聲明插件類繼承 QObject 及插件想要提供的接口。
  2. 使用 Q_INTERFACES () 宏告訴 Qt 的 元對象係統 關於接口。
  3. 導齣插件使用 Q_EXPORT_PLUGIN2 () 宏。
  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 <QStringList>
#include <QImage>
#include <plugandpaint/interfaces.h>
class ExtraFiltersPlugin : public QObject, public FilterInterface
{
    Q_OBJECT
    Q_INTERFACES(FilterInterface)
public:
    QStringList filters() const;
    QImage filterImage(const QString &filter, const QImage &image,
                       QWidget *parent);
};
					

The 插件和描繪 範例文檔編製會詳細闡述此過程。另請參閱 創建自定義 Widget 為 Qt Designer for information about issues that are specific to Qt Designer . You can also take a look at the 迴顯插件範例 is a more trivial example on how to implement a plugin that extends Qt applications. Please note that a QCoreApplication 必須已初始化,在可以加載插件之前。

定位插件

Qt 應用程序自動知道哪些插件可用,因為插件存儲在標準插件子目錄下。應用程序不要求采用任何代碼查找和加載插件,由於 Qt 會自動處理它們。

在開發期間,插件目錄為 QTDIR/plugins (在哪裏 QTDIR is the directory where Qt is installed), with each type of plugin in a subdirectory for that type, e.g. styles . If you want your applications to use plugins and you don't want to use the standard plugins path, have your installation process determine the path you want to use for the plugins, and save the path, e.g. using QSettings ,供應用程序運行時讀取。然後,應用程序可以調用 QCoreApplication::addLibraryPath () with this path and your plugins will be available to the application. Note that the final part of the path (e.g., styles ) 無法更改。

If you want the plugin to be loadable then one approach is to create a subdirectory under the application and place the plugin in that directory. If you distribute any of the plugins that come with Qt (the ones located in the plugins directory), you must copy the sub-directory under plugins 插件,位於應用程序根文件夾下 (即:不包括 plugins 目錄)。

注意: In Symbian all binaries must be located in the directory \sys\bin, so each Qt plugin has a stub with the same basename as the plugin dll and suffix ".qtplugin" to make Qt extension plugins work similarly to other platforms. When trying to locate the plugin, Qt actually looks for the stub instead of the plugin binary. While plugin stub files have the suffix ".qtplugin", they can still be loaded also by specifying a filename with the normal library suffix ".dll" for QPluginLoader , so normally application developer doesn't need to care about the different suffix of the stub. Because of the way applications can be installed on ROM or various other drives in Symbian, Qt looks for the stub from the same directory on all available drives if it is not located in the given directory when loading a plugin.

有關部署的更多信息,見 部署 Qt 應用程序 and 部署插件 文檔編製。

靜態插件

將插件包括在應用程序中的正常且最靈活方式,是將其編譯成單獨隨附的動態庫,並在運行時檢測並加載。

Plugins can be linked statically against your application. If you build the static version of Qt, this is the only option for including Qt's predefined plugins. Using static plugins makes the deployment less error-prone, but has the disadvantage that no functionality from plugins can be added without a complete rebuild and redistribution of the application.

When compiled as a static library, Qt provides the following static plugins:

Plugin name 類型 描述
qtaccessiblecompatwidgets 可訪問性 Accessibility for Qt 3 support widgets
qtaccessiblewidgets 可訪問性 Accessibility for Qt widgets
qdecorationdefault Decorations (Qt Extended) Default style
qdecorationwindows Decorations (Qt Extended) Windows style
qgif Image formats GIF
qjpeg Image formats JPEG
qmng Image formats MNG
qico Image formats ICO
qsvg Image formats SVG
qtiff Image formats TIFF
qimsw_multi Input methods (Qt Extended) Input Method Switcher
qwstslibmousehandler Mouse drivers (Qt Extended) tslib mouse
qgfxtransformed Graphic drivers (Qt Extended) Transformed screen
qgfxvnc Graphic drivers (Qt Extended) VNC
qscreenvfb Graphic drivers (Qt Extended) Virtual frame buffer
qsqldb2 SQL driver IBM DB2
qsqlibase SQL driver Borland InterBase
qsqlite SQL driver SQLite version 3
qsqlite2 SQL driver SQLite version 2
qsqlmysql SQL driver MySQL
qsqloci SQL driver Oracle (OCI)
qsqlodbc SQL driver Open Database Connectivity (ODBC)
qsqlpsql SQL driver PostgreSQL
qsqltds SQL driver Sybase Adaptive Server (TDS)
qcncodecs Text codecs Simplified Chinese (People's Republic of China)
qjpcodecs Text codecs 日語
qkrcodecs Text codecs 韓語
qtwcodecs Text codecs Traditional Chinese (Taiwan)

To link statically against those plugins, you need to use the Q_IMPORT_PLUGIN () macro in your application and you need to add the required plugins to your build using QTPLUGIN . For example, in your main.cpp :

#include <QApplication>
#include <QtPlugin>
Q_IMPORT_PLUGIN(qjpeg)
Q_IMPORT_PLUGIN(qgif)
Q_IMPORT_PLUGIN(qkrcodecs)
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    ...
    return app.exec();
}
					

.pro 文件對於應用程序而言,需要以下條目:

QTPLUGIN     += qjpeg \
                qgif \
                qkrcodecs
					

創建自己的靜態插件也是可能的,通過以下這些步驟:

  1. 添加 CONFIG += static 到插件的 .pro 文件。
  2. 使用 Q_IMPORT_PLUGIN () 宏在應用程序中。
  3. 鏈接應用程序與插件庫,使用 LIBS .pro 文件。

插件和描繪 範例和關聯的 基本工具 插件,瞭解如何做到這的有關細節。

注意: If you are not using qmake to build your application you need to make sure that the QT_STATICPLUGIN 預處理器宏有定義。

部署和調試插件

The 部署插件 文檔涵蓋采用應用程序部署插件和調試它們 (當齣現問題時) 的過程。

另請參閱 QPluginLoader , QLibrary ,和 插件和描繪範例 .