Beispiel für eine Container-Erweiterung
Erstellen eines benutzerdefinierten mehrseitigen Plugins für den „ Qt Widgets -Designer“.
Das Beispiel „Container-Erweiterung“ zeigt, wie man mithilfe der Klasse „ QDesignerContainerExtension “ ein benutzerdefiniertes mehrseitiges Plugin für den „ Qt Widgets Designer“ erstellt.
Qt Widgets Designer-UI-Editors, der die Option zum Einfügen einer Seite vor der aktuellen Seite in ein Objekt zeigt" src="images/containerextension-example.webp" title="Screenshot des Qt Widgets Designer-UI-Editors, der die Option zum Einfügen einer Seite vor der aktuellen Seite in ein Objekt zeigt"/>
Um ein benutzerdefiniertes Widget bereitzustellen, das mit dem „ Qt Widgets “ Designer verwendet werden kann, müssen wir eine in sich geschlossene Implementierung bereitstellen. In diesem Beispiel verwenden wir ein benutzerdefiniertes mehrseitiges Widget, das zur Demonstration der Container-Erweiterungsfunktion entwickelt wurde.
Eine Erweiterung ist ein Objekt, das das Verhalten v Qt Widgets -Designer verändert. Die ` QDesignerContainerExtension ` ermöglicht es dem ` Qt Widgets -Designer`, ein benutzerdefiniertes mehrseitiges Widget zu verwalten und zu bearbeiten, d. h. Seiten zum Widget hinzuzufügen und daraus zu entfernen.
Im „ Qt Widgets Designer“ stehen vier Arten von Erweiterungen zur Verfügung:
- QDesignerMemberSheetExtension bietet eine Erweiterung, mit der Sie die Mitgliedsfunktionen eines Widgets bearbeiten können, die bei der Konfiguration von Verbindungen im Modus zur Bearbeitung von Signalen und Slots des „ Qt Widgets “-Designers angezeigt werden.
- QDesignerPropertySheetExtension bietet eine Erweiterung, mit der Sie die Eigenschaften eines Widgets bearbeiten können, die im Eigenschafteneditor des „ Qt Widgets -Designers“ angezeigt werden.
- QDesignerTaskMenuExtension bietet eine Erweiterung, mit der Sie benutzerdefinierte Menüeinträge zum Aufgabenmenü des „ Qt Widgets “-Designers hinzufügen können.
- QDesignerContainerExtension bietet eine Erweiterung, mit der Sie Seiten zu einem mehrseitigen Container-Plugin im „ Qt Widgets “-Designer hinzufügen (und löschen) können.
Sie können alle Erweiterungen nach dem gleichen Muster wie in diesem Beispiel verwenden, wobei Sie lediglich die jeweilige Basisklasse der Erweiterung ersetzen müssen. Weitere Informationen finden Sie unter Qt Widgets Designer C++ Classes.
Das Beispiel „Container-Erweiterung“ besteht aus vier Klassen:
MultiPageWidgetist ein benutzerdefiniertes Container-Widget, mit dem der Benutzer dessen Seiten bearbeiten und füllen sowie mithilfe einer Combobox zwischen diesen navigieren kann.MultiPageWidgetPluginmacht die Klasse „MultiPageWidget“ für den „ Qt Widgets “-Designer verfügbar.MultiPageWidgetExtensionFactoryerstellt ein „MultiPageWidgetContainerExtension“-Objekt.MultiPageWidgetContainerExtensionstellt die Container-Erweiterung bereit.
Projektdateien für benutzerdefinierte Widget-Plugins benötigen einige zusätzliche Informationen, um sicherzustellen, dass sie im „ Qt Widgets Designer“ funktionieren. Beispielsweise sind benutzerdefinierte Widget-Plugins auf Komponenten angewiesen, die mit dem „ Qt Widgets Designer“ bereitgestellt werden, und dies muss in den von uns verwendeten Projektdateien angegeben werden. Wir werden uns zunächst die Projektdateien des Plugins ansehen.
Anschließend werden wir die Klasse „ MultiPageWidgetPlugin “ näher betrachten und einen Blick auf die Klassen „ MultiPageWidgetExtensionFactory “ und „ MultiPageWidgetContainerExtension “ werfen. Abschließend werden wir kurz die Klassendefinition von „ MultiPageWidget “ betrachten.
Projektdateien
CMake
In den Projektdateien muss angegeben werden, dass ein Plugin erstellt werden soll, das mit den „ Qt Widgets Designer“-Bibliotheken verknüpft ist:
find_package(Qt6 REQUIRED COMPONENTS Core Designer Gui Widgets)
qt_add_plugin(containerextension)
target_link_libraries(containerextension PUBLIC
Qt::Core
Qt::Designer
Qt::Gui
Qt::Widgets
)Das folgende Beispiel zeigt, wie die Header- und Quelldateien des Widgets hinzugefügt werden:
target_sources(containerextension PRIVATE
multipagewidget.cpp multipagewidget.h
multipagewidgetcontainerextension.cpp multipagewidgetcontainerextension.h
multipagewidgetextensionfactory.cpp multipagewidgetextensionfactory.h
multipagewidgetplugin.cpp multipagewidgetplugin.h
)Wir stellen eine Implementierung der Plugin-Schnittstelle bereit, damit „ Qt Widgets Designer“ das benutzerdefinierte Widget nutzen kann. In diesem speziellen Beispiel stellen wir zudem Implementierungen der Container-Erweiterungsschnittstelle und der Erweiterungsfabrik bereit.
Es ist wichtig sicherzustellen, dass das Plugin an einem Ort installiert wird, der von „ Qt Widgets Designer“ durchsucht wird. Dazu geben wir einen Zielpfad für das Projekt an und fügen ihn der Liste der zu installierenden Elemente hinzu:
set(INSTALL_EXAMPLEDIR "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_PLUGINS}/designer")
install(TARGETS containerextension
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)Die Container-Erweiterung wird als Bibliothek erstellt. Sie wird bei der Installation des Projekts (mit „ ninja install “ oder einem gleichwertigen Installationsverfahren) zusammen mit den anderen Qt Widgets -Designer-Plugins installiert.
Weitere Informationen zu Plugins finden Sie in der Dokumentation „How to Create Qt Plugins “.
qmake
Das folgende Beispiel zeigt, wie ein Plugin mit den Bibliotheken des „ Qt Widgets “ Designers verknüpft wird:
TEMPLATE = lib
CONFIG += plugin
QT += widgets designerDas folgende Beispiel zeigt, wie die Header- und Quelldateien des Widgets hinzugefügt werden:
HEADERS += multipagewidget.h \
multipagewidgetplugin.h \
multipagewidgetcontainerextension.h \
multipagewidgetextensionfactory.h
SOURCES += multipagewidget.cpp \
multipagewidgetplugin.cpp \
multipagewidgetcontainerextension.cpp \
multipagewidgetextensionfactory.cpp
OTHER_FILES += multipagewidget.jsonDas folgende Beispiel zeigt, wie ein Plugin im Plugin-Pfad des „ Qt Widgets “-Designers installiert wird:
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += targetKlassendefinition von `MultiPageWidgetPlugin`
Die Klasse „ MultiPageWidgetPlugin “ stellt die Klasse „ MultiPageWidget “ dem „ Qt Widgets Designer“ zur Verfügung. Ihre Definition ähnelt der Plugin-Klasse aus dem Beispiel „Custom Widget Plugin“, das ausführlich erläutert wird. Die Teile der Klassendefinition, die spezifisch für dieses bestimmte benutzerdefinierte Widget sind, sind der Klassenname und einige private Slots:
#ifndef MULTIPAGEWIDGETPLUGIN_H
#define MULTIPAGEWIDGETPLUGIN_H
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
class QIcon;
class QWidget;
class MultiPageWidgetPlugin: public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidget")
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
explicit MultiPageWidgetPlugin(QObject *parent = nullptr);
QString name() const override;
QString group() const override;
QString toolTip() const override;
QString whatsThis() const override;
QString includeFile() const override;
QIcon icon() const override;
bool isContainer() const override;
QWidget *createWidget(QWidget *parent) override;
bool isInitialized() const override;
void initialize(QDesignerFormEditorInterface *formEditor) override;
QString domXml() const override;
private slots:
void currentIndexChanged(int index);
void pageTitleChanged(const QString &title);
private:
bool initialized = false;
};
#endifDie Plugin-Klasse liefert dem „ Qt Widgets “-Designer grundlegende Informationen zu unserem Plugin, wie beispielsweise dessen Klassennamen und die zugehörige Include-Datei. Darüber hinaus weiß sie, wie Instanzen des „ MultiPageWidget “-Widgets erstellt werden. „ MultiPageWidgetPlugin “ definiert außerdem die Funktion „ initialize()“, die aufgerufen wird, nachdem das Plugin in den „ Qt Widgets “-Designer geladen wurde. Der Parameter „ QDesignerFormEditorInterface “ dieser Funktion bietet dem Plugin einen Zugang zu allen APIs des „ Qt Widgets “-Designers.
Im Falle eines mehrseitigen Widgets wie dem unseren müssen wir außerdem zwei private Slots implementieren, nämlich `currentIndexChanged()` und `pageTitleChanged()`, um den Eigenschaftseditor v Qt Widgets -Designer aktualisieren zu können, sobald der Benutzer eine andere Seite aufruft oder einen der Seitentitel ändert. Um jeder Seite einen eigenen Titel zuweisen zu können, haben wir uns dafür entschieden, die Eigenschaft „ QWidget::windowTitle “ zum Speichern des Seitentitels zu verwenden (weitere Informationen finden Sie in der Implementierung der Klasse „MultiPageWidget“ in „containerextension/multipagewidget.cpp“). Beachten Sie, dass es derzeit keine Möglichkeit gibt, den Seiten eine benutzerdefinierte Eigenschaft (z. B. einen Seitentitel) hinzuzufügen, ohne eine vordefinierte Eigenschaft als Platzhalter zu verwenden.
Die Klasse „ MultiPageWidgetPlugin “ erbt sowohl von „ QObject “ als auch von „ QDesignerCustomWidgetInterface “. Bei der Verwendung von Mehrfachvererbung ist es wichtig, sicherzustellen, dass alle Schnittstellen (d. h. die Klassen, die nicht von „ Q_OBJECT “ erben) dem Metobjektsystem mithilfe des Makros „ Q_INTERFACES()“ bekannt gemacht werden. Dies ermöglicht es dem „ Qt Widgets Designer“, mit „ qobject_cast()“ nach unterstützten Schnittstellen abzufragen, wobei lediglich ein „ QObject “-Zeiger verwendet wird.
Um sicherzustellen, dass Qt das Widget als Plugin erkennt, müssen relevante Informationen über das Widget durch Hinzufügen des Makros „ Q_PLUGIN_METADATA() “ exportiert werden:
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidget")Mit diesem Makro kann der „ Qt Widgets “-Designer auf das benutzerdefinierte Widget zugreifen und es erstellen. Ohne dieses Makro kann der „ Qt Widgets “-Designer das Widget nicht verwenden.
Implementierung der Klasse „MultiPageWidgetPlugin“
Die Implementierung der Klasse „MultiPageWidgetPlugin“ entspricht größtenteils der Plugin-Klasse aus dem Beispiel „Benutzerdefiniertes Widget-Plugin “:
MultiPageWidgetPlugin::MultiPageWidgetPlugin(QObject *parent)
: QObject(parent)
{
}
QString MultiPageWidgetPlugin::name() const
{
return u"MultiPageWidget"_s;
}
QString MultiPageWidgetPlugin::group() const
{
return u"Display Widgets [Examples]"_s;
}
QString MultiPageWidgetPlugin::toolTip() const
{
return {};
}
QString MultiPageWidgetPlugin::whatsThis() const
{
return {};
}
QString MultiPageWidgetPlugin::includeFile() const
{
return u"multipagewidget.h"_s;
}
QIcon MultiPageWidgetPlugin::icon() const
{
return {};
}
bool MultiPageWidgetPlugin::isInitialized() const
{
return initialized;
}Eine der Funktionen, die sich unterscheidet, ist die Funktion `isContainer()`, die in diesem Beispiel den Wert „true“ zurückgibt, da unser benutzerdefiniertes Widget als Container verwendet werden soll.
bool MultiPageWidgetPlugin::isContainer() const
{
return true;
}Eine weitere Funktion, die sich unterscheidet, ist die Funktion zum Erstellen unseres benutzerdefinierten Widgets:
QWidget *MultiPageWidgetPlugin::createWidget(QWidget *parent)
{
auto *widget = new MultiPageWidget(parent);
connect(widget, &MultiPageWidget::currentIndexChanged,
this, &MultiPageWidgetPlugin::currentIndexChanged);
connect(widget, &MultiPageWidget::pageTitleChanged,
this, &MultiPageWidgetPlugin::pageTitleChanged);
return widget;
}Zusätzlich zum Erstellen und Zurückgeben des Widgets verbinden wir das Signal `currentIndexChanged()` unseres benutzerdefinierten Container-Widgets mit dem Slot `currentIndexChanged()` des Plugins, um sicherzustellen, dass der Eigenschafteneditor des „ Qt Widgets “-Designers aktualisiert wird, sobald der Benutzer eine andere Seite aufruft. Außerdem verbinden wir das Signal `pageTitleChanged()` des Widgets mit dem Slot `pageTitleChanged()` des Plugins.
Der Slot `currentIndexChanged()` wird immer dann aufgerufen, wenn das Signal `currentIndexChanged()` unseres benutzerdefinierten Widgets ausgelöst wird, d. h. immer dann, wenn der Benutzer eine andere Seite aufruft:
void MultiPageWidgetPlugin::currentIndexChanged(int index)
{
Q_UNUSED(index);
auto *widget = qobject_cast<MultiPageWidget*>(sender());Zunächst ermitteln wir das Objekt, das das Signal aussendet, mithilfe der Funktionen ` QObject::sender()` und ` qobject_cast()`. Wird die Funktion in einem durch ein Signal aktivierten Slot aufgerufen, gibt ` QObject::sender()` einen Zeiger auf das Objekt zurück, das das Signal gesendet hat; andernfalls gibt sie 0 zurück.
if (widget) {
auto *form = QDesignerFormWindowInterface::findFormWindow(widget);
if (form)
form->emitSelectionChanged();
}
}Sobald wir das Widget haben, können wir den Eigenschaftseditor aktualisieren. „ Qt Widgets Designer“ nutzt die Klasse „ QDesignerPropertySheetExtension “, um seinen Eigenschaftseditor zu versorgen, und immer wenn ein Widget in seinem Arbeitsbereich ausgewählt wird, fragt „ Qt Widgets Designer“ nach der Eigenschaftsblatt-Erweiterung des Widgets ab und aktualisiert den Eigenschaftseditor.
Wir möchten also dem „ Qt Widgets “-Designer mitteilen, dass sich die interne Auswahl unseres Widgets geändert hat: Zunächst verwenden wir die statische Funktion ` QDesignerFormWindowInterface::findFormWindow()` , um das ` QDesignerFormWindowInterface `-Objekt abzurufen, das das Widget enthält. Die Klasse ` QDesignerFormWindowInterface ` ermöglicht es Ihnen, Formularfenster abzufragen und zu bearbeiten, die im Arbeitsbereich des „ Qt Widgets “-Designers angezeigt werden. Anschließend müssen wir lediglich das Signal ` emitSelectionChanged()` auslösen, wodurch eine Aktualisierung des Eigenschaftseditors erzwungen wird.
Beim Ändern eines Seitentitels reicht eine generische Aktualisierung des Eigenschaftseditors nicht aus, da tatsächlich die Eigenschaftserweiterung der Seite aktualisiert werden muss. Aus diesem Grund müssen wir auf das ` QDesignerPropertySheetExtension `-Objekt der Seite zugreifen, deren Titel wir ändern möchten. Die Klasse ` QDesignerPropertySheetExtension ` ermöglicht es Ihnen ebenfalls, die Eigenschaften eines Widgets zu bearbeiten, doch um die Erweiterung zu erhalten, müssen wir zunächst auf den Erweiterungsmanager v Qt Widgets -Designer zugreifen:
void MultiPageWidgetPlugin::pageTitleChanged(const QString &title)
{
Q_UNUSED(title);
auto *widget = qobject_cast<MultiPageWidget*>(sender());
if (widget) {
auto *page = widget->widget(widget->currentIndex());
auto *form = QDesignerFormWindowInterface::findFormWindow(widget);Auch hier ermitteln wir zunächst das Widget, das das Signal aussendet, mithilfe der Funktionen ` QObject::sender()` und ` qobject_cast()`. Anschließend ermitteln wir die aktuelle Seite anhand des Widgets, das das Signal ausgesendet hat, und verwenden die statische Funktion ` QDesignerFormWindowInterface::findFormWindow()`, um das Formular abzurufen, das unser Widget enthält.
auto *editor = form->core();
auto *manager = editor->extensionManager();Da wir nun das Formularfenster haben, stellt die Klasse ` QDesignerFormWindowInterface ` die Funktion ` core()` zur Verfügung, die das aktuelle ` QDesignerFormEditorInterface `-Objekt zurückgibt. Die Klasse ` QDesignerFormEditorInterface ` ermöglicht den Zugriff auf die verschiedenen Komponenten von ` Qt Designer`. Insbesondere gibt die Funktion ` QDesignerFormEditorInterface::extensionManager()` eine Referenz auf den aktuellen Erweiterungsmanager zurück.
auto *sheet = qt_extension<QDesignerPropertySheetExtension*>(manager, page);
const int propertyIndex = sheet->indexOf(QLatin1String("windowTitle"));
sheet->setChanged(propertyIndex, true);
}
}
}Sobald wir den Erweiterungsmanager haben, können wir das Erweiterungsblatt aktualisieren: Zunächst rufen wir mithilfe der Funktion „ qt_extension()“ die Eigenschaft „extension“ für die Seite ab, deren Titel wir ändern möchten. Anschließend rufen wir mithilfe der Funktion „ QDesignerPropertySheetExtension::indexOf()“ den Index für den Seitentitel ab. Wie bereits erwähnt, haben wir uns dafür entschieden, die Eigenschaft „ QWidget::windowTitle “ zur Speicherung des Seitentitels zu verwenden (weitere Informationen finden Sie in der Implementierung der Klasse „MultiPageWidget“ in `containerextension/multipagewidget.cpp`). Schließlich erzwingen wir implizit eine Aktualisierung des Eigenschaftsblatts der Seite, indem wir die Funktion ` QDesignerPropertySheetExtension::setChanged()` aufrufen.
void MultiPageWidgetPlugin::initialize(QDesignerFormEditorInterface *formEditor)
{
if (initialized)
return;Beachten Sie auch die Funktion `initialize()`: Die Funktion ` initialize() ` nimmt ein ` QDesignerFormEditorInterface `-Objekt als Argument entgegen.
auto *manager = formEditor->extensionManager();Beim Erstellen von Erweiterungen, die mit benutzerdefinierten Widget-Plugins verbunden sind, müssen wir auf den aktuellen Erweiterungsmanager des „ Qt Widgets Designer“ zugreifen, den wir über den Parameter „ QDesignerFormEditorInterface “ abrufen.
Die Klasse „ QExtensionManager “ ermöglicht nicht nur die Bearbeitung der Eigenschaften eines Widgets, sondern stellt auch Funktionen zur Erweiterungsverwaltung für den „ Qt Widgets Designer“ bereit. Mithilfe des aktuellen Erweiterungsmanagers des „ Qt Widgets Designers“ können Sie die Erweiterung für ein bestimmtes Objekt abrufen. Außerdem können Sie eine Erweiterung für ein bestimmtes Objekt registrieren oder deren Registrierung aufheben. Beachten Sie, dass eine Erweiterung ein Objekt ist, das das Verhalten des „ Qt Widgets Designers“ verändert.
Bei der Registrierung einer Erweiterung wird eigentlich die zugehörige Erweiterungsfabrik registriert. Im „ Qt Widgets Designer“ werden Erweiterungsfabriken verwendet, um benannte Erweiterungen bei Bedarf nachzuschlagen und zu erstellen. In diesem Beispiel wird die Container-Erweiterung also erst dann erstellt, wenn der „ Qt Widgets Designer“ wissen muss, ob das zugehörige Widget ein Container ist oder nicht.
auto *factory = new MultiPageWidgetExtensionFactory(manager);
Q_ASSERT(manager != nullptr);
manager->registerExtensions(factory, Q_TYPEID(QDesignerContainerExtension));
initialized = true;
}Wir erstellen ein ` MultiPageWidgetExtensionFactory `-Objekt, das wir mithilfe des aktuellen ` extension manager ` des ` Qt Widgets `-Designers registrieren, das aus dem Parameter ` QDesignerFormEditorInterface ` abgerufen wird. Das erste Argument ist die neu erstellte Factory und das zweite Argument ist eine Erweiterungskennung, bei der es sich um eine Zeichenkette handelt. Das Makro ` Q_TYPEID() ` wandelt die Zeichenkette einfach in eine ` QLatin1String` um.
Die Klasse „ MultiPageWidgetExtensionFactory “ ist eine Unterklasse von „ QExtensionFactory “. Wenn der „ Qt Widgets Designer“ wissen muss, ob ein Widget ein Container ist oder nicht, durchläuft der Erweiterungsmanager des „ Qt Widgets Designers“ alle registrierten Fabriken und ruft die erste auf, die in der Lage ist, eine Container-Erweiterung für dieses Widget zu erstellen. Diese Fabrik erstellt wiederum ein „ MultiPageWidgetExtension “-Objekt.
QString MultiPageWidgetPlugin::domXml() const
{
return uR"(
<ui language="c++">
<widget class="MultiPageWidget" name="multipagewidget">
<widget class="QWidget" name="page"/>
</widget>
<customwidgets>
<customwidget>
<class>MultiPageWidget</class>
<extends>QWidget</extends>
<addpagemethod>addPage</addpagemethod>
</customwidget>
</customwidgets>
</ui>)"_s;
}Sehen Sie sich abschließend die Funktion „ domXml() “ an. Diese Funktion enthält Standardeinstellungen für das Widget im Standard-XML-Format, das vom „ Qt Widgets Designer“ verwendet wird. In diesem Fall geben wir die erste Seite des Containers an; alle Anfangsseiten eines mehrseitigen Widgets müssen innerhalb dieser Funktion angegeben werden.
Klassendefinition von `MultiPageWidgetExtensionFactory`
Die Klasse „ MultiPageWidgetExtensionFactory “ erbt von „ QExtensionFactory “, die eine Standard-Erweiterungsfabrik für den „ Qt Widgets “-Designer bereitstellt.
class MultiPageWidgetExtensionFactory: public QExtensionFactory
{
Q_OBJECT
public:
explicit MultiPageWidgetExtensionFactory(QExtensionManager *parent = nullptr);
protected:
QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const override;
};Der Zweck der Unterklasse besteht darin, die Funktion ` QExtensionFactory::createExtension()` neu zu implementieren, damit sie eine Containererweiterung für ` MultiPageWidget ` erstellen kann.
Implementierung der Klasse „MultiPageWidgetExtensionFactory“
Der Konstruktor der Klasse ruft lediglich den Konstruktor der Basisklasse „ QExtensionFactory “ auf:
MultiPageWidgetExtensionFactory::MultiPageWidgetExtensionFactory(QExtensionManager *parent)
: QExtensionFactory(parent)
{}Wie oben beschrieben, wird die Factory aufgerufen, wenn der „ Qt Widgets Designer“ wissen muss, ob das zugehörige Widget ein Container ist oder nicht.
QObject *MultiPageWidgetExtensionFactory::createExtension(QObject *object,
const QString &iid,
QObject *parent) const
{
auto *widget = qobject_cast<MultiPageWidget*>(object);
if (widget && (iid == Q_TYPEID(QDesignerContainerExtension)))
return new MultiPageWidgetContainerExtension(widget, parent);
return nullptr;
}Qt Widgets Das Verhalten des Designers ist unabhängig davon, ob die angeforderte Erweiterung mit einem Container, einem Member-Sheet, einem Property-Sheet oder einem Aufgabenmenü verknüpft ist: Sein Erweiterungsmanager durchläuft alle registrierten Erweiterungsfabriken und ruft für jede davon „ createExtension() “ auf, bis eine davon reagiert und die angeforderte Erweiterung erstellt.
Daher prüfen wir in „ MultiPageWidgetExtensionFactory::createExtension() “ als Erstes, ob das „ QObject “, für das die Erweiterung angefordert wird, tatsächlich ein „ MultiPageWidget “-Objekt ist. Anschließend prüfen wir, ob es sich bei der angeforderten Erweiterung um eine Container-Erweiterung handelt.
Ist das Objekt ein „MultiPageWidget“, das eine Container-Erweiterung anfordert, erstellen wir ein „ MultiPageWidgetExtension “-Objekt und geben es zurück. Andernfalls geben wir einfach einen Null-Zeiger zurück, sodass der Erweiterungsmanager des „ Qt Widgets Designer“ seine Suche unter den registrierten Fabriken fortsetzen kann.
Klassendefinition von „MultiPageWidgetContainerExtension“
Die Klasse „ MultiPageWidgetContainerExtension “ erbt von „ QDesignerContainerExtension “, wodurch Sie im „ Qt Widgets Designer“ Seiten zu einem mehrseitigen Container-Plugin hinzufügen (und löschen) können.
class MultiPageWidgetContainerExtension: public QObject,
public QDesignerContainerExtension
{
Q_OBJECT
Q_INTERFACES(QDesignerContainerExtension)
public:
explicit MultiPageWidgetContainerExtension(MultiPageWidget *widget, QObject *parent);
bool canAddWidget() const override;
void addWidget(QWidget *widget) override;
int count() const override;
int currentIndex() const override;
void insertWidget(int index, QWidget *widget) override;
bool canRemove(int index) const override;
void remove(int index) override;
void setCurrentIndex(int index) override;
QWidget *widget(int index) const override;
private:
MultiPageWidget *myWidget;
};Es ist wichtig zu beachten, dass die Klasse „ QDesignerContainerExtension “ lediglich dazu dient, dem „ Qt Widgets Designer“ Zugriff auf die Funktionalität Ihres benutzerdefinierten mehrseitigen Widgets zu gewähren; Ihr benutzerdefiniertes mehrseitiges Widget muss die den Funktionen der Erweiterung entsprechenden Funktionen implementieren.
Beachten Sie außerdem, dass wir einen Konstruktor implementieren, der zwei Argumente entgegennimmt: das übergeordnete Widget und das „ MultiPageWidget “-Objekt, für das das Aufgabenmenü angefordert wird.
QDesignerContainerExtension Stellt standardmäßig einige Menüeinträge im Aufgabenmenü des „ Qt Widgets Designer“ bereit, über die der Benutzer Seiten zum zugehörigen benutzerdefinierten mehrseitigen Widget im Arbeitsbereich des „ Qt Widgets Designer“ hinzufügen oder löschen kann.
Implementierung der Klasse „MultiPageWidgetContainerExtension“
Im Konstruktor speichern wir die Referenz auf das als Parameter übergebene „ MultiPageWidget “-Objekt, d. h. das mit der Erweiterung verknüpfte Widget. Diese benötigen wir später, um auf das benutzerdefinierte mehrseitige Widget zuzugreifen und die angeforderten Aktionen auszuführen.
MultiPageWidgetContainerExtension::MultiPageWidgetContainerExtension(MultiPageWidget *widget,
QObject *parent)
: QObject(parent)
, myWidget(widget)
{
}Damit der „ Qt Widgets Designer“ Ihr benutzerdefiniertes mehrseitiges Widget vollständig verwalten und bearbeiten kann, müssen Sie alle Funktionen von „ QDesignerContainerExtension “ neu implementieren:
bool MultiPageWidgetContainerExtension::canAddWidget() const
{
return true;
}
void MultiPageWidgetContainerExtension::addWidget(QWidget *widget)
{
myWidget->addPage(widget);
}
int MultiPageWidgetContainerExtension::count() const
{
return myWidget->count();
}
int MultiPageWidgetContainerExtension::currentIndex() const
{
return myWidget->currentIndex();
}Sie müssen „ canAddWidget()“ und „ addWidget()“ neu implementieren, um eine bestimmte Seite zum Container hinzuzufügen, „ count()“, um die Anzahl der Seiten im Container zurückzugeben, sowie „ currentIndex()“, um den Index der aktuell ausgewählten Seite zurückzugeben.
void MultiPageWidgetContainerExtension::insertWidget(int index, QWidget *widget)
{
myWidget->insertPage(index, widget);
}
bool MultiPageWidgetContainerExtension::canRemove(int index) const
{
Q_UNUSED(index);
return true;
}
void MultiPageWidgetContainerExtension::remove(int index)
{
myWidget->removePage(index);
}
void MultiPageWidgetContainerExtension::setCurrentIndex(int index)
{
myWidget->setCurrentIndex(index);
}
QWidget* MultiPageWidgetContainerExtension::widget(int index) const
{
return myWidget->widget(index);
}Sie müssen die Methoden ` insertWidget()` neu implementieren, um eine bestimmte Seite unter einem bestimmten Index zum Container hinzuzufügen, sowie die Methoden ` canRemove()` und ` remove()`, um die Seite unter einem bestimmten Index zu löschen, die Methode ` setCurrentIndex()`, um den Index der aktuell ausgewählten Seite festzulegen, und schließlich die Methode ` widget()`, um die Seite unter einem bestimmten Index zurückzugeben.
Definition der Klasse „MultiPageWidget“
Die Klasse „MultiPageWidget“ ist ein benutzerdefiniertes Container-Widget, mit dem der Benutzer die Seiten bearbeiten und füllen sowie mithilfe einer Combobox zwischen diesen navigieren kann.
class MultiPageWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex)
Q_PROPERTY(QString pageTitle READ pageTitle WRITE setPageTitle STORED false)
public:
explicit MultiPageWidget(QWidget *parent = nullptr);
QSize sizeHint() const override;
int count() const;
int currentIndex() const;
QWidget *widget(int index);
QString pageTitle() const;
public slots:
void addPage(QWidget *page);
void insertPage(int index, QWidget *page);
void removePage(int index);
void setPageTitle(const QString &newTitle);
void setCurrentIndex(int index);
private slots:
void pageWindowTitleChanged();
signals:
void currentIndexChanged(int index);
void pageTitleChanged(const QString &title);
private:
QStackedWidget *stackWidget;
QComboBox *comboBox;
};Zu beachten ist vor allem, dass Ihr benutzerdefiniertes Mehrseiten-Widget Funktionen implementieren muss, die den Member-Funktionen von ` QDesignerContainerExtension` entsprechen, da die Klasse ` QDesignerContainerExtension ` lediglich dazu dient, einen Zugriff über ` Qt Designer ` auf die Funktionen Ihres benutzerdefinierten Mehrseiten-Widgets bereitzustellen.
Darüber hinaus deklarieren wir die Eigenschaften „ currentIndex “ und „ pageTitle “ sowie die dazugehörigen Set- und Get-Funktionen. Indem wir diese Attribute als Eigenschaften deklarieren, ermöglichen wir es dem „ Qt Widgets Designer“, sie auf dieselbe Weise zu verwalten wie die Eigenschaften, die das „MultiPageWidget“-Widget von „ QWidget “ und „ QObject “ erbt – beispielsweise mithilfe des Eigenschaftseditors.
Beachten Sie das Attribut „ STORED “ in der Deklaration der Eigenschaft „ pageTitle “: Das Attribut „ STORED “ kennzeichnet die Persistenz, d. h., es legt fest, ob der Wert der Eigenschaft beim Speichern des Zustands eines Objekts beibehalten werden muss. Wie oben erwähnt, haben wir uns dafür entschieden, den Seitentitel mithilfe der Eigenschaft „ QWidget::windowTitle “ zu speichern, um jeder Seite einen eigenen Titel zuweisen zu können. Aus diesem Grund ist die Eigenschaft „ pageTitle “ eine „Schein“-Eigenschaft, die zu Bearbeitungszwecken bereitgestellt wird und nicht gespeichert werden muss.
Außerdem müssen wir die Signale `currentIndexChanged()` und `pageTitleChanged()` implementieren und ausgeben, um sicherzustellen, dass der Eigenschaftseditor v Qt Widgets -Designer aktualisiert wird, sobald der Benutzer eine andere Seite aufruft oder einen der Seitentitel ändert.
Weitere Details finden Sie in der Implementierung der Klasse `MultiPageWidget` in ` containerextension/multipagewidget.cpp `.
© 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.