Wie man Qt-Plugins erstellt

Qt bietet zwei APIs zur Erstellung von Plugins:

  • Eine High-Level-API zum Schreiben von Erweiterungen für Qt selbst, wie z. B. benutzerdefinierte Datenbanktreiber, Bildformate, Text-Codecs und benutzerdefinierte Stile.
  • Eine Low-Level-API zur Erweiterung von Qt-Anwendungen.

Wenn Sie zum Beispiel eine benutzerdefinierte QStyle Unterklasse schreiben und Qt-Anwendungen diese dynamisch laden lassen möchten, würden Sie die API auf höherer Ebene verwenden.

Da die übergeordnete API auf der untergeordneten API aufbaut, sind einige Probleme für beide gleich.

Wenn Sie Plugins für die Verwendung mit Qt Widgets Designer bereitstellen möchten, lesen Sie bitte den Abschnitt Erstellen benutzerdefinierter Widget-Plugins.

Die High-Level-API: Schreiben von Qt-Erweiterungen

Um ein Plugin zu schreiben, das Qt selbst erweitert, müssen Sie die entsprechende Plugin-Basisklasse unterklassifizieren, ein paar Funktionen implementieren und ein Makro hinzufügen.

Es gibt mehrere Plugin-Basisklassen. Abgeleitete Plugins werden standardmäßig in Unterverzeichnissen des Standard-Plugin-Verzeichnisses gespeichert. Qt findet keine Plugins, wenn sie nicht im entsprechenden Verzeichnis gespeichert sind.

Die folgende Tabelle fasst die Plugin-Basisklassen zusammen. Einige der Klassen sind privat und werden daher nicht dokumentiert. Sie können sie verwenden, aber es gibt kein Kompatibilitätsversprechen mit späteren Qt-Versionen.

BasisklasseVerzeichnis NameQt-ModulSchlüssel Case Sensitivity
QAccessibleBridgePluginaccessiblebridgeQt GUIGroß-/Kleinschreibung
QImageIOPluginimageformatsQt GUIGroß-/Kleinschreibung beachten
QPictureFormatPlugin (veraltet)pictureformatsQt GUIGroß-/Kleinschreibung empfindlich
QBearerEnginePluginbearerQt NetworkFallabhängig
QPlatformInputContextPluginplatforminputcontextsQt-Plattform-AbstraktionGroß-/Kleinschreibung nicht beachten
QPlatformIntegrationPluginplatformsQt-Plattform-AbstraktionGroß-/Kleinschreibung unempfindlich
QPlatformThemePluginplatformthemesQt-Plattform-AbstraktionGroß-/Kleinschreibung unempfindlich
QPlatformPrinterSupportPluginprintsupportQt Print SupportGroß-/Kleinschreibung unempfindlich
QSGContextPluginscenegraphQt QuickGroß-/Kleinschreibung beachten
QSqlDriverPluginsqldriversQt SQLGroß-/Kleinschreibung beachten
QIconEnginePluginiconenginesQt SVGGroß-/Kleinschreibung unempfindlich
QAccessiblePluginaccessibleQt WidgetsGroß-/Kleinschreibung beachten
QStylePluginstylesQt WidgetsGroß-/Kleinschreibung unempfindlich

Wenn Sie eine neue Dokumentanzeigeklasse mit dem Namen JsonViewer haben, die Sie als Plugin zur Verfügung stellen möchten, muss die Klasse wie folgt definiert werden (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:
    bool openJsonFile();

    QTreeView *m_tree;
    QListWidget *m_toplevel = nullptr;
    QJsonDocument m_root;

    QPointer<QLineEdit> m_searchKey;
};

Stellen Sie sicher, dass sich die Klassenimplementierung in einer .cpp Datei befindet:

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

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

Darüber hinaus ist für die meisten Plugins eine json-Datei (jsonviewer.json) erforderlich, die Metadaten zur Beschreibung des Plugins enthält. Für Dokument-Viewer-Plugins enthält sie einfach den Namen des Viewer-Plugins.

{ "Keys": [ "jsonviewer" ] }

Die Art der Informationen, die in der json-Datei enthalten sein müssen, hängt vom Plugin ab. Einzelheiten zu den Informationen, die in der Datei enthalten sein müssen, finden Sie in der Klassendokumentation.

Für Datenbanktreiber, Bildformate, Text-Codecs und die meisten anderen Plugin-Typen ist keine explizite Objekterstellung erforderlich. Qt findet und erstellt sie nach Bedarf.

Plugin-Klassen können die Implementierung zusätzlicher Funktionen erfordern. Siehe die Klassendokumentation für Details zu den virtuellen Funktionen, die für jeden Plugin-Typ neu implementiert werden müssen.

Die Document Viewer Demo zeigt, wie man ein Plugin implementiert, das den strukturierten Inhalt einer Datei anzeigt. Jedes Plugin reimplementiert daher virtuelle Funktionen, die

  • das Plugin identifizieren
  • die MIME-Typen zurückgeben, die es unterstützt
  • darüber informieren, ob es einen Inhalt gibt, der angezeigt werden soll und
  • wie die Inhalte dargestellt werden
    QString viewerName() const override { return QLatin1StringView(staticMetaObject.className()); };
    QStringList supportedMimeTypes() const override;
    bool hasContent() const override;
    bool supportsOverview() const override { return true; }

Die Low-Level-API: Erweitern von Qt-Anwendungen

Zusätzlich zu Qt selbst, können Qt-Anwendungen durch Plugins erweitert werden. Dies erfordert, dass die Anwendung Plugins mit Hilfe von QPluginLoader erkennt und lädt. In diesem Zusammenhang können Plugins beliebige Funktionen bereitstellen und sind nicht auf Datenbanktreiber, Bildformate, Textcodecs, Stile und andere Arten von Plugins beschränkt, die die Funktionalität von Qt erweitern.

Um eine Anwendung durch Plugins erweiterbar zu machen, sind die folgenden Schritte erforderlich:

  1. Definieren Sie eine Reihe von Schnittstellen (Klassen mit nur rein virtuellen Funktionen), die zur Kommunikation mit den Plugins verwendet werden.
  2. Verwenden Sie das Q_DECLARE_INTERFACE() Makro, um dem Meta-Objektsystem von Qt die Schnittstelle mitzuteilen.
  3. Verwenden Sie QPluginLoader in der Anwendung, um die Plugins zu laden.
  4. Verwenden Sie qobject_cast(), um zu testen, ob ein Plugin eine bestimmte Schnittstelle implementiert.

Das Schreiben eines Plugins beinhaltet diese Schritte:

  1. Deklarieren Sie eine Plugin-Klasse, die von QObject und von den Schnittstellen erbt, die das Plugin zur Verfügung stellen will.
  2. Verwenden Sie das Q_INTERFACES() Makro, um dem Meta-Objektsystem von Qt die Schnittstellen mitzuteilen.
  3. Exportieren Sie das Plugin mit dem Q_PLUGIN_METADATA() Makro.

Hier ist zum Beispiel die Definition einer Schnittstellenklasse:

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

Hier ist die Schnittstellendeklaration:

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

Siehe auch Erstellen von benutzerdefinierten Widgets für Qt Widgets Designer für Informationen zu Problemen, die spezifisch für Qt Widgets Designer sind.

Auffinden von Plugins

Qt-Anwendungen wissen automatisch, welche Plugins verfügbar sind, da Plugins in den Standard-Plugin-Unterverzeichnissen gespeichert sind. Aus diesem Grund benötigen Anwendungen keinen Code, um Plugins zu finden und zu laden, da Qt dies automatisch erledigt.

Während der Entwicklung ist das Verzeichnis für Plugins QTDIR/plugins (wobei QTDIR das Verzeichnis ist, in dem Qt installiert ist), mit jedem Plugin-Typ in einem Unterverzeichnis für diesen Typ, z.B. styles. Wenn Sie möchten, dass Ihre Anwendungen Plugins verwenden und Sie nicht den Standardpfad für Plugins verwenden möchten, lassen Sie Ihren Installationsprozess den Pfad bestimmen, den Sie für die Plugins verwenden möchten, und speichern Sie den Pfad, z.B. durch Verwendung von QSettings, damit die Anwendung ihn lesen kann, wenn sie läuft. Die Anwendung kann dann QCoreApplication::addLibraryPath() mit diesem Pfad aufrufen und Ihre Plugins stehen der Anwendung zur Verfügung. Beachten Sie, dass der letzte Teil des Pfades (z. B. styles) nicht geändert werden kann.

Wenn Sie möchten, dass das Plugin geladen werden kann, besteht eine Möglichkeit darin, ein Unterverzeichnis unter der Anwendung zu erstellen und das Plugin in diesem Verzeichnis abzulegen. Wenn Sie eines der mit Qt gelieferten Plugins (die sich im Verzeichnis plugins befinden) weitergeben, müssen Sie das Unterverzeichnis unter plugins, in dem sich das Plugin befindet, in das Stammverzeichnis Ihrer Anwendung kopieren (d. h. das Verzeichnis plugins nicht mit einbeziehen).

Weitere Informationen zum Deployment finden Sie in der Dokumentation Deploying Qt Applications and Deploying Plugins.

Statische Plugins

Der normale und flexibelste Weg, ein Plugin in eine Anwendung einzubinden, besteht darin, es in eine dynamische Bibliothek zu kompilieren, die separat ausgeliefert wird und zur Laufzeit erkannt und geladen wird.

Plugins können statisch in Ihre Anwendung eingebunden werden. Wenn Sie die statische Version von Qt erstellen, ist dies die einzige Möglichkeit, die vordefinierten Plugins von Qt einzubinden. Die Verwendung statischer Plugins macht das Deployment weniger fehleranfällig, hat aber den Nachteil, dass keine Funktionalität von Plugins hinzugefügt werden kann, ohne die Anwendung komplett neu zu erstellen und zu verteilen.

CMake und qmake fügen automatisch die Plugins hinzu, die typischerweise von den verwendeten Qt-Modulen benötigt werden, während speziellere Plugins manuell hinzugefügt werden müssen. Die Standardliste der automatisch hinzugefügten Plugins kann pro Typ überschrieben werden.

Die Standardeinstellungen sind auf ein optimales Out-of-the-Box-Erlebnis abgestimmt, können aber die Anwendung unnötig aufblähen. Es wird empfohlen, die Befehlszeile des Linkers zu überprüfen und unnötige Plugins zu entfernen.

Um zu bewirken, dass statische Plugins tatsächlich gelinkt und instanziiert werden, sind auch Q_IMPORT_PLUGIN()-Makros im Anwendungscode erforderlich, aber diese werden automatisch vom Build-System generiert und dem Anwendungsprojekt hinzugefügt.

Importieren statischer Plugins in CMake

Um Plugins in einem CMake-Projekt statisch zu linken, müssen Sie den Befehl qt_import_plugins aufrufen.

Zum Beispiel wird das Linux libinput Plugin standardmäßig nicht importiert. Der folgende Befehl importiert es:

qt_import_plugins(myapp INCLUDE Qt::QLibInputPlugin)

Um das minimale Plattformintegrations-Plugin anstelle des Standard-Plugins Qt Platform Adaptation zu verknüpfen, verwenden Sie:

qt_import_plugins(myapp
    INCLUDE_BY_TYPE platforms Qt::MinimalIntegrationPlugin
)

Ein anderer typischer Anwendungsfall ist es, nur einen bestimmten Satz von imageformats Plugins zu verknüpfen:

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

Wenn Sie die Verlinkung eines beliebigen imageformats -Plugins verhindern wollen, verwenden Sie:

qt_import_plugins(myapp
    EXCLUDE_BY_TYPE imageformats
)

Wenn Sie das Hinzufügen eines Standard-Plugins deaktivieren möchten, verwenden Sie die Option NO_DEFAULT von qt_import_plugins.

Importieren von statischen Plugins in qmake

In einem qmake-Projekt müssen Sie die benötigten Plugins mit QTPLUGIN zu Ihrem Build hinzufügen:

QTPLUGIN += qlibinputplugin

Um z.B. das Minimal-Plugin anstelle des Standard-Plugins Qt Platform Adaptation einzubinden, verwenden Sie:

QTPLUGIN.platforms = qminimal

Wenn Sie wollen, dass weder das Standard- noch das minimale QPA-Plugin automatisch verknüpft wird, verwenden Sie:

QTPLUGIN.platforms = -

Wenn Sie nicht möchten, dass alle zu QTPLUGIN hinzugefügten Plugins automatisch verlinkt werden, entfernen Sie import_plugins aus der Variable CONFIG:

CONFIG -= import_plugins

Statische Plugins erstellen

Es ist auch möglich, Ihre eigenen statischen Plugins zu erstellen, indem Sie die folgenden Schritte ausführen:

  1. Übergeben Sie die Option STATIC an den Befehl qt_add_plugin in Ihrem CMakeLists.txt. Für ein qmake-Projekt fügen Sie CONFIG += static zur .pro Datei Ihres Plugins hinzu.
  2. Verwenden Sie das Q_IMPORT_PLUGIN() Makro in Ihrer Anwendung.
  3. Verwenden Sie das Q_INIT_RESOURCE()-Makro in Ihrer Anwendung, wenn das Plugin qrc-Dateien ausliefert.
  4. Verknüpfen Sie Ihre Anwendung mit Ihrer Plugin-Bibliothek mit target_link_libraries in Ihrer CMakeLists.txt oder LIBS in Ihrer .pro Datei.

Siehe das Plug & Paint-Beispiel und das zugehörige Basic Tools-Plugin für weitere Informationen.

Hinweis: Wenn Sie nicht CMake oder qmake zum Erstellen Ihres Plugins verwenden, müssen Sie sicherstellen, dass das Präprozessormakro QT_STATICPLUGIN definiert ist.

Laden von Plugins

Plugin-Typen (statisch oder gemeinsam genutzt) und Betriebssysteme erfordern spezifische Ansätze zum Auffinden und Laden von Plugins. Es ist nützlich, eine Abstraktion für das Laden von Plugins zu implementieren.

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

QPluginLoader::staticInstances() gibt eine QObjectList mit einem Zeiger auf jedes statisch gelinkte Plugin zurück

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

Gemeinsam genutzte Plugins befinden sich in ihren Einsatzverzeichnissen, die möglicherweise eine betriebssystemspezifische Handhabung erfordern.

   // Gemeinsame Plugins laden   QDir pluginsDir = QDir(QApplication::applicationDirPath());#if defined(Q_OS_WINDOWS)pluginsDir.cd("app"_L1);#elif defined(Q_OS_DARWIN) if (pluginsDir.dirName() == "MacOS"_L1) { pluginsDir.cdUp(); pluginsDir.cdUp(); pluginsDir.cdUp(); }#endif const auto entryList = pluginsDir.entryList(QDir::Files); for(const QString &fileName: entryList) { QPluginLoader loader(pluginsDir.absoluteFilePath(Dateiname));        QObject *plugin = loader.instance(); if (plugin) addViewer(plugin);#if 0 else            qDebug() << loader.errorString();
#endif} }

Bereitstellen und Debuggen von Plugins

Das Dokument Deploying Plugins behandelt den Prozess der Bereitstellung von Plugins mit Anwendungen und die Fehlersuche, wenn Probleme auftreten.

Siehe auch QPluginLoader und QLibrary.

© 2025 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.