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.
Basisklasse | Verzeichnis Name | Qt-Modul | Schlüssel Case Sensitivity |
---|---|---|---|
QAccessibleBridgePlugin | accessiblebridge | Qt GUI | Groß-/Kleinschreibung |
QImageIOPlugin | imageformats | Qt GUI | Groß-/Kleinschreibung beachten |
QPictureFormatPlugin (veraltet) | pictureformats | Qt GUI | Groß-/Kleinschreibung empfindlich |
QBearerEnginePlugin | bearer | Qt Network | Fallabhängig |
QPlatformInputContextPlugin | platforminputcontexts | Qt-Plattform-Abstraktion | Groß-/Kleinschreibung nicht beachten |
QPlatformIntegrationPlugin | platforms | Qt-Plattform-Abstraktion | Groß-/Kleinschreibung unempfindlich |
QPlatformThemePlugin | platformthemes | Qt-Plattform-Abstraktion | Groß-/Kleinschreibung unempfindlich |
QPlatformPrinterSupportPlugin | printsupport | Qt Print Support | Groß-/Kleinschreibung unempfindlich |
QSGContextPlugin | scenegraph | Qt Quick | Groß-/Kleinschreibung beachten |
QSqlDriverPlugin | sqldrivers | Qt SQL | Groß-/Kleinschreibung beachten |
QIconEnginePlugin | iconengines | Qt SVG | Groß-/Kleinschreibung unempfindlich |
QAccessiblePlugin | accessible | Qt Widgets | Groß-/Kleinschreibung beachten |
QStylePlugin | styles | Qt Widgets | Groß-/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:
- Definieren Sie eine Reihe von Schnittstellen (Klassen mit nur rein virtuellen Funktionen), die zur Kommunikation mit den Plugins verwendet werden.
- Verwenden Sie das Q_DECLARE_INTERFACE() Makro, um dem Meta-Objektsystem von Qt die Schnittstelle mitzuteilen.
- Verwenden Sie QPluginLoader in der Anwendung, um die Plugins zu laden.
- Verwenden Sie qobject_cast(), um zu testen, ob ein Plugin eine bestimmte Schnittstelle implementiert.
Das Schreiben eines Plugins beinhaltet diese Schritte:
- Deklarieren Sie eine Plugin-Klasse, die von QObject und von den Schnittstellen erbt, die das Plugin zur Verfügung stellen will.
- Verwenden Sie das Q_INTERFACES() Makro, um dem Meta-Objektsystem von Qt die Schnittstellen mitzuteilen.
- 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:
- Übergeben Sie die Option
STATIC
an den Befehl qt_add_plugin in IhremCMakeLists.txt
. Für ein qmake-Projekt fügen SieCONFIG += static
zur.pro
Datei Ihres Plugins hinzu. - Verwenden Sie das Q_IMPORT_PLUGIN() Makro in Ihrer Anwendung.
- Verwenden Sie das Q_INIT_RESOURCE()-Makro in Ihrer Anwendung, wenn das Plugin qrc-Dateien ausliefert.
- Verknüpfen Sie Ihre Anwendung mit Ihrer Plugin-Bibliothek mit target_link_libraries in Ihrer
CMakeLists.txt
oderLIBS
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.