Sur cette page

Comment créer des plugins Qt

Qt propose deux API pour créer des plugins :

  • Une API de haut niveau permettant de développer des extensions pour Qt lui-même, telles que des pilotes de bases de données personnalisés, des formats d’image, des codecs de texte et des styles.
  • Une API de bas niveau permettant d'étendre les applications Qt.

Par exemple, si vous souhaitez écrire une sous-classe personnalisée de ` QStyle ` et que les applications Qt la chargent dynamiquement, vous utiliserez l'API de haut niveau.

L'API de haut niveau s'appuyant sur l'API de bas niveau, certains problèmes sont communs aux deux.

Si vous souhaitez fournir des plugins destinés à être utilisés avec Qt Widgets Designer, consultez la section Création de plugins de widgets personnalisés.

L'API de haut niveau : écriture d'extensions Qt

Pour écrire un plugin qui étend Qt lui-même, il suffit de créer une sous-classe de la classe de base du plugin appropriée, d’implémenter quelques fonctions et d’ajouter une macro.

Il existe plusieurs classes de base de plugins. Les plugins dérivés sont stockés par défaut dans des sous-répertoires du répertoire standard des plugins. Qt ne trouvera pas les plugins s’ils ne sont pas stockés dans le répertoire approprié.

Le tableau suivant récapitule les classes de base des plugins. Certaines de ces classes sont privées et ne sont donc pas documentées. Vous pouvez les utiliser, mais leur compatibilité avec les versions ultérieures de Qt n’est pas garantie.

Classe de baseNom du répertoireModule QtSensibilité à la casse de la clé
QAccessibleBridgePluginaccessiblebridgeQt GUISensible à la casse
QImageIOPluginimageformatsQt GUIDistinction entre majuscules et minuscules
QPictureFormatPlugin (obsolète)pictureformatsQt GUIDistinction entre majuscules et minuscules
QBearerEnginePluginbearerQt NetworkSensibilité à la casse
QPlatformInputContextPluginplatforminputcontextsAbstraction de la plateforme QtSans distinction de majuscules/minuscules
QPlatformIntegrationPluginplatformsAbstraction de la plateforme QtInsensible à la casse
QPlatformThemePluginplatformthemesAbstraction de la plateforme QtInsensible à la casse
QPlatformPrinterSupportPluginprintsupportQt Print SupportInsensible à la casse
QSGContextPluginscenegraphQt QuickSensible à la casse
QSqlDriverPluginsqldriversQt SQLSensible à la casse
QIconEnginePluginiconenginesQt SVGSans distinction de casse
QAccessiblePluginaccessibleQt WidgetsSensible à la casse
QStylePluginstylesQt WidgetsSans distinction de majuscules et minuscules

Si vous disposez d'une nouvelle classe de visualisation de documents appelée « JsonViewer » que vous souhaitez rendre disponible en tant que plugin, cette classe doit être définie comme suit (jsonviewer.h) :

class JsonViewer : public ViewerInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.DocumentViewer.ViewerInterface/1.0" FILE "jsonviewer.json")
    Q_INTERFACES(ViewerInterface)
public:
    JsonViewer();
    ~JsonViewer() override;
private:
    void retranslate() override;
    bool openJsonFile();

    QTreeView *m_tree = nullptr;
    QListWidget *m_toplevel = nullptr;
    QJsonDocument m_root;
    QAction *m_expandAllAction = nullptr;
    QAction *m_collapseAllAction = nullptr;
};

Assurez-vous que l'implémentation de la classe se trouve dans un fichier .cpp:

JsonViewer::JsonViewer()
    : m_expandAllAction(new QAction(this)),
      m_collapseAllAction(new QAction(this))

{
    connect(this, &AbstractViewer::uiInitialized, this, &JsonViewer::setupJsonUi);

    m_expandAllAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::ZoomIn));
    m_collapseAllAction->setIcon(QIcon::fromTheme(QIcon::ThemeIcon::ZoomOut));
}

void JsonViewer::init(QFile *file, QWidget *parent, QMainWindow *mainWindow)
{
    AbstractViewer::init(file, new QTreeView(parent), mainWindow);
    setTranslationBaseName("jsonviewer"_L1);
    m_tree = qobject_cast<QTreeView *>(widget());
}

De plus, un fichier JSON (jsonviewer.json) contenant les métadonnées décrivant le plugin est requis pour la plupart des plugins. Pour les plugins de visualisation de documents, il contient simplement le nom du plugin de visualisation.

{ "Keys": [ "jsonviewer" ] }

Le type d'informations à fournir dans le fichier JSON dépend du plugin. Consultez la documentation de la classe pour plus de détails sur les informations que doit contenir le fichier.

Pour les pilotes de base de données, les formats d'image, les codecs de texte et la plupart des autres types de plugins, aucune création explicite d'objet n'est requise. Qt les trouvera et les créera selon les besoins.

Les classes de plug-ins peuvent nécessiter l'implémentation de fonctions supplémentaires. Consultez la documentation de la classe pour plus de détails sur les fonctions virtuelles qui doivent être réimplémentées pour chaque type de plug-in.

La démo « Document Viewer » montre comment implémenter un plugin qui affiche le contenu structuré d’un fichier. Chaque plugin réimplémente donc des fonctions virtuelles, qui

  • identifient le plugin
  • renvoient les types MIME qu’il prend en charge
  • indiquent s’il y a du contenu à afficher et
  • comment ce contenu est présenté
    QString viewerName() const override { return QLatin1StringView(staticMetaObject.className()); };
    QStringList supportedMimeTypes() const override;
    bool hasContent() const override;
    bool supportsOverview() const override { return true; }

L'API de bas niveau : étendre les applications Qt

Outre Qt lui-même, les applications Qt peuvent être étendues à l’aide de plugins. Pour cela, l’application doit détecter et charger les plugins à l’aide de QPluginLoader. Dans ce contexte, les plugins peuvent fournir des fonctionnalités arbitraires et ne se limitent pas aux pilotes de bases de données, aux formats d’image, aux codecs de texte, aux styles et autres types de plugins qui étendent les fonctionnalités de Qt.

Pour rendre une application extensible via des plugins, il faut suivre les étapes suivantes :

  1. Définir un ensemble d’interfaces (classes ne comportant que des fonctions virtuelles pures) utilisées pour communiquer avec les plugins.
  2. Utiliser la macro ` Q_DECLARE_INTERFACE()` pour signaler l’interface au système de méta-objets de Qt.
  3. Utiliser ` QPluginLoader ` dans l'application pour charger les plugins.
  4. Utiliser ` qobject_cast()` pour vérifier si un plugin implémente une interface donnée.

L'écriture d'un plugin implique les étapes suivantes :

  1. Déclarez une classe de plugin héritant de ` QObject ` et des interfaces que le plugin souhaite fournir.
  2. Utilisez la macro Q_INTERFACES() pour signaler ces interfaces au système de méta-objets de Qt.
  3. Exporter le plugin à l'aide de la macro ` Q_PLUGIN_METADATA()`.

Voici, par exemple, la définition d'une classe d'interface :

class ViewerInterface : public AbstractViewer
{
public:
    virtual ~ViewerInterface() = default;
};

Voici la déclaration de l'interface :

#define ViewerInterface_iid "org.qt-project.Qt.Examples.DocumentViewer.ViewerInterface/1.0"
Q_DECLARE_INTERFACE(ViewerInterface, ViewerInterface_iid)

Voir également Création de widgets personnalisés pour le concepteur d’ Qt Widgets s pour plus d’informations sur les problèmes spécifiques au concepteur d’ Qt Widgets s. Consultez l’exemple de plugin de backend de calendrier pour découvrir comment utiliser un plugin afin d’ajouter la prise en charge d’un système de calendrier personnalisé.

Recherche de plugins

Les applications Qt identifient automatiquement les plugins disponibles, car ceux-ci sont stockés dans les sous-répertoires standard dédiés aux plugins. De ce fait, les applications n'ont pas besoin de code pour rechercher et charger les plugins, puisque Qt s'en charge automatiquement.

Pendant le développement, le répertoire des plugins est QTDIR/plugins (où QTDIR correspond au répertoire d'installation de Qt), chaque type de plugin se trouvant dans un sous-répertoire dédié, par exemple styles. Si vous souhaitez que vos applications utilisent des plugins et que vous ne souhaitez pas utiliser le chemin d’accès standard aux plugins, faites en sorte que votre processus d’installation détermine le chemin d’accès que vous souhaitez utiliser pour les plugins, puis enregistrez ce chemin, par exemple à l’aide de ` QSettings`, afin que l’application puisse le lire lors de son exécution. L’application peut alors appeler la fonction ` QCoreApplication::addLibraryPath()` avec ce chemin d’accès et vos plugins seront alors disponibles pour l’application. Notez que la partie finale du chemin d’accès (par exemple, ` styles`) ne peut pas être modifiée.

Si vous souhaitez que le plugin puisse être chargé, une approche consiste à créer un sous-répertoire sous l'application et à y placer le plugin. Si vous distribuez l’un des plugins fournis avec Qt (ceux situés dans le répertoire plugins ), vous devez copier le sous-répertoire situé sous plugins où se trouve le plugin dans le dossier racine de votre application (c’est-à-dire sans inclure le répertoire plugins ).

Pour plus d’informations sur le déploiement, consultez la documentation intitulée « Déploiement d’applications Qt » et « Déploiement de plug-ins ».

Plug-ins statiques

La méthode habituelle et la plus flexible pour intégrer un plugin à une application consiste à le compiler en une bibliothèque dynamique fournie séparément, qui est détectée et chargée lors de l'exécution.

Les plugins peuvent être liés de manière statique à votre application. Si vous compilez la version statique de Qt, c'est la seule option disponible pour intégrer les plugins prédéfinis de Qt. L'utilisation de plugins statiques rend le déploiement moins sujet aux erreurs, mais présente l'inconvénient de ne pas permettre l'ajout de fonctionnalités issues des plugins sans une recompilation et une redistribution complètes de l'application.

CMake et qmake ajoutent automatiquement les plugins généralement requis par les modules Qt utilisés, tandis que les plugins plus spécialisés doivent être ajoutés manuellement. La liste par défaut des plugins ajoutés automatiquement peut être redéfinie par type.

Les paramètres par défaut sont optimisés pour offrir une expérience optimale dès l’installation, mais peuvent alourdir inutilement l’application. Il est recommandé d’examiner la ligne de commande de l’éditeur de liens et de supprimer les plugins superflus.

Pour que les plugins statiques soient effectivement liés et instanciés, les macros Q_IMPORT_PLUGIN() sont également nécessaires dans le code de l'application, mais celles-ci sont automatiquement générées par le système de compilation et ajoutées à votre projet d'application.

Importation de plugins statiques dans CMake

Pour lier statiquement des plugins dans un projet CMake, vous devez appeler la commande ` qt_import_plugins() `.

Par exemple, le plugin « libinput » pour Linux n'est pas importé par défaut. La commande suivante permet de l'importer :

qt_import_plugins(myapp INCLUDE Qt::QLibInputPlugin)

Pour lier le plugin d'intégration de plateforme minimale à la place du plugin Qt Platform Adaptation par défaut, utilisez :

qt_import_plugins(myapp
    INCLUDE_BY_TYPE platforms Qt::MinimalIntegrationPlugin
)

Un autre cas d'utilisation courant consiste à lier uniquement un ensemble spécifique de plugins d'imageformats:

qt_import_plugins(myapp
    INCLUDE_BY_TYPE imageformats Qt::QJpegPlugin Qt::QGifPlugin
)

Si vous souhaitez empêcher l'association de tout plugin imageformats, utilisez :

qt_import_plugins(myapp
    EXCLUDE_BY_TYPE imageformats
)

Si vous souhaitez désactiver l'ajout de tout plugin par défaut, utilisez l'option NO_DEFAULT de la fonction qt_import_plugins().

Importation de plugins statiques dans qmake

Dans un projet qmake, vous devez ajouter les plugins requis à votre compilation à l’aide de ` QTPLUGIN` :

QTPLUGIN += qlibinputplugin

Par exemple, pour lier le plugin minimal à la place du plugin de Qt Platform Adaptation par défaut, utilisez :

QTPLUGIN.platforms = qminimal

Si vous ne souhaitez que ni le plugin par défaut, ni le plugin QPA minimal ne soient liés automatiquement, utilisez :

QTPLUGIN.platforms = -

Si vous ne souhaitez pas que tous les plug-ins ajoutés à QTPLUGIN soient automatiquement liés, supprimez « import_plugins » de la variable « CONFIG » :

CONFIG -= import_plugins

Création de plug-ins statiques

Il est également possible de créer vos propres plug-ins statiques en suivant les étapes suivantes :

  1. Passez l'option STATIC à la commande qt_add_plugin() dans votre fichier CMakeLists.txt. Pour un projet qmake, ajoutez CONFIG += static au fichier .pro de votre plugin.
  2. Utilisez la macro Q_IMPORT_PLUGIN() dans votre application.
  3. Utilisez la macro Q_INIT_RESOURCE() dans votre application si le plugin fournit des fichiers qrc.
  4. Liez votre application à la bibliothèque de votre plugin à l’aide de ` target_link_libraries ` dans votre fichier ` CMakeLists.txt ` ou de ` LIBS ` dans votre fichier ` .pro `.

Consultez l’exemple Plug & Paint et le plugin Basic Tools associé pour plus de détails sur la marche à suivre.

Remarque : si vous n’utilisez pas CMake ou qmake pour compiler votre plugin, vous devez vous assurer que la macro de préprocesseur ` QT_STATICPLUGIN ` est définie.

Chargement des plugins

Les types de plug-ins (statiques ou partagés) et les systèmes d'exploitation nécessitent des approches spécifiques pour localiser et charger les plug-ins. Il est utile d'implémenter une abstraction pour le chargement des plug-ins.

void ViewerFactory::loadViewerPlugins()
{
    if (!m_viewers.isEmpty())
        return;

QPluginLoader::staticInstances() renvoie une instance de ` QObjectList ` contenant un pointeur vers chaque plugin lié statiquement

    // Load static plugins
    const QObjectList &staticPlugins = QPluginLoader::staticInstances();
    for (auto *plugin : staticPlugins)
        addViewer(plugin);

Les plugins partagés se trouvent dans leurs répertoires de déploiement, ce qui peut nécessiter une gestion spécifique au système d’exploitation.

   // Chargement des plugins partagés
    QDir pluginsDir = QDir(QApplication::applicationDirPath());
#if defined(Q_OS_DARWIN)
    if (pluginsDir.exists("../PlugIns"_L1)) { // version installée
        pluginsDir.cd("../PlugIns"_L1);
    } else {
        pluginsDir.cd("../../../../plugins"_L1); // version non installée
    }
#elif defined(Q_OS_WIN)
    if (pluginsDir.exists("plugins"_L1)) { // version non installée
        pluginsDir.cd("plugins"_L1);
    } else {
        pluginsDir.cd("../plugins"_L1); // version installée
    }
#else
    pluginsDir.cd("../plugins"_L1); // versions installée et non installée
#endif

   // qDebug("Chargement des plugins depuis %s...", qUtf8Printable(pluginsDir.path()));
    const auto entryList = pluginsDir.entryList(QDir::Files);
    for (const QString&fileName: entryList) {
        QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
        QObject*plugin = loader.instance();
        if (plugin)
            addViewer(plugin);
#if 0
        else
            qDebug() << loader.errorString();
#endif
    }
}

Déploiement et débogage des plugins

Le document « Déploiement des plugins » décrit la procédure à suivre pour déployer des plugins avec des applications et les déboguer en cas de problème.

Voir également QPluginLoader et QLibrary.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.