Sur cette page

Exemple d'extension de conteneur

Création d'un plugin multi-pages personnalisé pour Qt Widgets Designer.

L'exemple d'extension de conteneur montre comment créer un plugin multipage personnalisé pour Qt Widgets Designer à l'aide de la classe QDesignerContainerExtension.

Capture d'écran de l'éditeur d'interface utilisateur de <span translate=Qt Widgets Designer montrant l'option d'insertion d'une page avant la page actuelle dans un objet." src="images/containerextension-example.webp" title="Capture d'écran de l'éditeur d'interface utilisateur de Qt Widgets Designer montrant l'option d'insertion d'une page avant la page actuelle dans un objet."/>

Pour fournir un widget personnalisé pouvant être utilisé avec Qt Widgets Designer, nous devons fournir une implémentation autonome. Dans cet exemple, nous utilisons un widget multipage personnalisé conçu pour présenter la fonction d'extension de conteneur.

Une extension est un objet qui modifie le comportement de Qt Widgets Designer. QDesignerContainerExtension permet à Qt Widgets Designer de gérer et de manipuler un widget multipage personnalisé, c'est-à-dire d'ajouter et de supprimer des pages au widget.

Il existe quatre types d'extensions disponibles dans Qt Widgets Designer:

  • QDesignerMemberSheetExtension fournit une extension qui vous permet de manipuler les fonctions membres d'un widget qui s'affichent lors de la configuration des connexions à l'aide du mode d'édition des signaux et des emplacements de Qt Widgets Designer.
  • QDesignerPropertySheetExtension fournit une extension qui vous permet de manipuler les propriétés d'un widget, affichée dans l'éditeur de propriétés de Qt Widgets Designer.
  • QDesignerTaskMenuExtension fournit une extension qui vous permet d'ajouter des entrées de menu personnalisées au menu des tâches de Qt Widgets Designer.
  • QDesignerContainerExtension fournit une extension qui vous permet d'ajouter (et de supprimer) des pages à un plugin de conteneur multipage dans Qt Widgets Designer.

Vous pouvez utiliser toutes les extensions en suivant le même schéma que dans cet exemple, en remplaçant uniquement la classe de base de l'extension concernée. Pour plus d'informations, voir Qt Widgets Designer C++ Classes.

L'exemple d'extension de conteneur se compose de quatre classes :

  • MultiPageWidget est un widget conteneur personnalisé qui permet à l'utilisateur de manipuler et de remplir ses pages, et de naviguer entre elles à l'aide d'une boîte combinée.
  • MultiPageWidgetPlugin expose la classe MultiPageWidget à Qt Widgets Designer.
  • MultiPageWidgetExtensionFactory crée un objet MultiPageWidgetContainerExtension.
  • MultiPageWidgetContainerExtension fournit l'extension du conteneur.

Les fichiers de projet pour les modules d'extension de widgets personnalisés ont besoin de quelques informations supplémentaires pour garantir qu'ils fonctionneront dans Qt Widgets Designer. Par exemple, les plugins de widgets personnalisés s'appuient sur des composants fournis avec Qt Widgets Designer, ce qui doit être spécifié dans les fichiers de projet que nous utilisons. Nous commencerons par examiner les fichiers de projet du plugin.

Ensuite, nous passerons en revue la classe MultiPageWidgetPlugin, puis les classes MultiPageWidgetExtensionFactory et MultiPageWidgetContainerExtension. Enfin, nous jetterons un coup d'œil rapide à la définition de la classe MultiPageWidget.

Fichiers de projet

CMake

Les fichiers de projet doivent indiquer qu'un plugin liant les bibliothèques Qt Widgets Designer doit être construit :

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
)

L'exemple suivant montre comment ajouter les fichiers d'en-tête et de source du widget :

target_sources(containerextension PRIVATE
    multipagewidget.cpp multipagewidget.h
    multipagewidgetcontainerextension.cpp multipagewidgetcontainerextension.h
    multipagewidgetextensionfactory.cpp multipagewidgetextensionfactory.h
    multipagewidgetplugin.cpp multipagewidgetplugin.h
)

Nous fournissons une implémentation de l'interface du plugin afin que Qt Widgets Designer puisse utiliser le widget personnalisé. Dans cet exemple particulier, nous fournissons également des implémentations de l'interface d'extension du conteneur et de la fabrique d'extension.

Il est important de s'assurer que le plugin est installé dans un emplacement qui peut être recherché par Qt Widgets Designer. Pour ce faire, nous spécifions un chemin cible pour le projet et l'ajoutons à la liste des éléments à installer :

   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}"
)

L'extension de conteneur est créée en tant que bibliothèque. Elle sera installée avec les autres plugins Qt Widgets Designer lors de l'installation du projet (à l'aide de ninja install ou d'une procédure d'installation équivalente).

Pour plus d'informations sur les plugins, voir la documentation How to Create Qt Plugins.

qmake

L'exemple suivant montre comment lier un plugin aux bibliothèques Qt Widgets Designer:

TEMPLATE = lib
CONFIG  += plugin

QT      += widgets designer

L'exemple suivant montre comment ajouter les fichiers d'en-tête et de source du widget :

HEADERS += multipagewidget.h \
           multipagewidgetplugin.h \
           multipagewidgetcontainerextension.h \
           multipagewidgetextensionfactory.h

SOURCES += multipagewidget.cpp \
           multipagewidgetplugin.cpp \
           multipagewidgetcontainerextension.cpp \
           multipagewidgetextensionfactory.cpp

OTHER_FILES += multipagewidget.json

L'exemple suivant montre comment installer un plugin dans le chemin des plugins de Qt Widgets Designer:

target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target

Définition de la classe MultiPageWidgetPlugin

La classe MultiPageWidgetPlugin expose la classe MultiPageWidget à Qt Widgets Designer. Sa définition est similaire à celle de la classe de plugin de l'exemple Custom Widget Plugin, qui est expliquée en détail. Les parties de la définition de la classe qui sont spécifiques à ce widget personnalisé particulier sont le nom de la classe et quelques emplacements privés :

#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;
};

#endif

La classe de plugin fournit à Qt Widgets Designer des informations de base sur notre plugin, telles que son nom de classe et son fichier d'inclusion. En outre, elle sait comment créer des instances du widget MultiPageWidget. MultiPageWidgetPlugin définit également la fonction initialize() qui est appelée après le chargement du plugin dans Qt Widgets Designer. Le paramètre QDesignerFormEditorInterface de la fonction fournit au plugin une passerelle vers toutes les API de Qt Widgets Designer.

Dans le cas d'un widget multipage comme le nôtre, nous devons également implémenter deux slots privés, currentIndexChanged() et pageTitleChanged(), afin de pouvoir mettre à jour l'éditeur de propriétés de Qt Widgets Designer chaque fois que l'utilisateur consulte une autre page ou modifie l'un des titres de la page. Pour pouvoir donner à chaque page son propre titre, nous avons choisi d'utiliser la propriété QWidget::windowTitle pour stocker le titre de la page (pour plus d'informations, voir l'implémentation de la classe MultiPageWidget dans containerextension/multipagewidget.cpp. Notez qu'il n'existe actuellement aucun moyen d'ajouter une propriété personnalisée (par exemple, un titre de page) aux pages sans utiliser une propriété prédéfinie en tant que placeholder.

La classe MultiPageWidgetPlugin hérite à la fois de QObject et de QDesignerCustomWidgetInterface. Il est important de se rappeler, lors de l'utilisation de l'héritage multiple, que toutes les interfaces (c'est-à-dire les classes qui n'héritent pas de Q_OBJECT) sont portées à la connaissance du système de métaobjets à l'aide de la macro Q_INTERFACES(). Cela permet à Qt Widgets Designer d'utiliser qobject_cast() pour rechercher les interfaces prises en charge en n'utilisant rien d'autre qu'un pointeur QObject.

Pour s'assurer que Qt Widgets reconnaisse le widget comme un plugin, exportez les informations pertinentes sur le widget en ajoutant la macro Q_PLUGIN_METADATA():

    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidget")

Grâce à cette macro, Qt Widgets Designer peut accéder au widget personnalisé et le construire. Sans cette macro, Qt Widgets Designer n'a aucun moyen d'utiliser le widget.

Mise en œuvre de la classe MultiPageWidgetPlugin

L'implémentation de la classe MultiPageWidgetPlugin est en grande partie équivalente à la classe de plugin de l'exemple Custom 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;
}

L'une des fonctions qui diffère est la fonction isContainer() qui renvoie true dans cet exemple puisque notre widget personnalisé est destiné à être utilisé comme conteneur.

bool MultiPageWidgetPlugin::isContainer() const
{
    return true;
}

Une autre fonction qui diffère est la fonction qui crée notre widget personnalisé :

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;
}

En plus de créer et de renvoyer le widget, nous connectons le signal currentIndexChanged() de notre widget conteneur personnalisé au slot currentIndexChanged() du plugin pour nous assurer que l'éditeur de propriétés de Qt Widgets Designer est mis à jour chaque fois que l'utilisateur consulte une autre page. Nous connectons également le signal pageTitleChanged() du widget au slot pageTitleChanged() du plugin.

Le slot currentIndexChanged() est appelé chaque fois que le signal currentIndexChanged() de notre widget personnalisé est émis, c'est-à-dire chaque fois que l'utilisateur consulte une autre page :

void MultiPageWidgetPlugin::currentIndexChanged(int index)
{
    Q_UNUSED(index);
    auto *widget = qobject_cast<MultiPageWidget*>(sender());

Tout d'abord, nous récupérons l'objet émettant le signal à l'aide des fonctions QObject::sender() et qobject_cast(). Si elle est appelée dans un slot activé par un signal, QObject::sender() renvoie un pointeur sur l'objet qui a envoyé le signal ; sinon, elle renvoie 0.

    if (widget) {
        auto *form = QDesignerFormWindowInterface::findFormWindow(widget);
        if (form)
            form->emitSelectionChanged();
    }
}

Une fois que nous avons le widget, nous pouvons mettre à jour l'éditeur de propriétés. Qt Widgets Designer utilise la classe QDesignerPropertySheetExtension pour alimenter son éditeur de propriétés, et chaque fois qu'un widget est sélectionné dans son espace de travail, Qt Widgets Designer demande l'extension de la feuille de propriétés du widget et met à jour l'éditeur de propriétés.

Ce que nous voulons faire, c'est notifier à Qt Widgets Designer que la sélection interne de notre widget a changé : Tout d'abord, nous utilisons la fonction statique QDesignerFormWindowInterface::findFormWindow() pour récupérer l'objet QDesignerFormWindowInterface contenant le widget. La classe QDesignerFormWindowInterface permet d'interroger et de manipuler les fenêtres de formulaire apparaissant dans l'espace de travail Qt Widgets Designer. Ensuite, tout ce que nous avons à faire est d'émettre son signal emitSelectionChanged(), forçant une mise à jour de l'éditeur de propriétés.

Lorsque l'on modifie le titre d'une page, un rafraîchissement générique de l'éditeur de propriétés ne suffit pas, car c'est en fait l'extension des propriétés de la page qui doit être mise à jour. C'est pourquoi nous devons accéder à l'objet QDesignerPropertySheetExtension de la page dont nous voulons modifier le titre. La classe QDesignerPropertySheetExtension permet également de manipuler les propriétés d'un widget, mais pour obtenir l'extension, nous devons d'abord accéder au gestionnaire d'extension de Qt Widgets Designer:

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);

Une fois encore, nous récupérons d'abord le widget qui émet le signal, à l'aide des fonctions QObject::sender() et qobject_cast(). Ensuite, nous récupérons la page actuelle du widget qui a émis le signal, et nous utilisons la fonction statique QDesignerFormWindowInterface::findFormWindow() pour récupérer le formulaire contenant notre widget.

            auto *editor = form->core();
            auto *manager = editor->extensionManager();

Maintenant que nous avons la fenêtre du formulaire, la classe QDesignerFormWindowInterface fournit la fonction core() qui renvoie l'objet QDesignerFormEditorInterface actuel. La classe QDesignerFormEditorInterface vous permet d'accéder aux différents composants de Qt Designer. En particulier, la fonction QDesignerFormEditorInterface::extensionManager() renvoie une référence au gestionnaire d'extension actuel.

            auto *sheet = qt_extension<QDesignerPropertySheetExtension*>(manager, page);
            const int propertyIndex = sheet->indexOf(QLatin1String("windowTitle"));
            sheet->setChanged(propertyIndex, true);
        }
    }
}

Une fois que nous avons le gestionnaire d'extension, nous pouvons mettre à jour la feuille d'extension : Tout d'abord, nous récupérons l'extension de la page dont nous voulons modifier le titre, à l'aide de la fonction qt_extension(). Ensuite, nous récupérons l'index du titre de la page à l'aide de la fonction QDesignerPropertySheetExtension::indexOf(). Comme indiqué précédemment, nous avons choisi d'utiliser la propriété QWidget::windowTitle pour stocker le titre de la page (pour plus d'informations, voir l'implémentation de la classe MultiPageWidget dans containerextension/multipagewidget.cpp. Enfin, nous forçons implicitement la mise à jour de la feuille de propriétés de la page en appelant la fonction QDesignerPropertySheetExtension::setChanged().

void MultiPageWidgetPlugin::initialize(QDesignerFormEditorInterface *formEditor)
{
    if (initialized)
        return;

Notez également la fonction initialize() : La fonction initialize() prend un objet QDesignerFormEditorInterface comme argument.

    auto *manager = formEditor->extensionManager();

Lors de la création d'extensions associées à des plugins de widgets personnalisés, nous devons accéder au gestionnaire d'extensions actuel de Qt Widgets Designer, que nous récupérons à partir du paramètre QDesignerFormEditorInterface.

En plus de vous permettre de manipuler les propriétés d'un widget, la classe QExtensionManager fournit des fonctions de gestion des extensions pour Qt Widgets Designer. En utilisant le gestionnaire d'extensions actuel de Qt Widgets Designer, vous pouvez récupérer l'extension d'un objet donné. Vous pouvez également enregistrer et désenregistrer une extension pour un objet donné. Rappelez-vous qu'une extension est un objet qui modifie le comportement de Qt Widgets Designer.

Lors de l'enregistrement d'une extension, c'est en fait la fabrique d'extensions associée qui est enregistrée. Dans Qt Widgets Designer, les fabriques d'extensions sont utilisées pour rechercher et créer des extensions nommées au fur et à mesure des besoins. Ainsi, dans cet exemple, l'extension de conteneur elle-même n'est pas créée tant que Qt Widgets Designer ne doit pas savoir si le widget associé est un conteneur ou non.

    auto *factory = new MultiPageWidgetExtensionFactory(manager);

    Q_ASSERT(manager != nullptr);
    manager->registerExtensions(factory, Q_TYPEID(QDesignerContainerExtension));

    initialized = true;
}

Nous créons un objet MultiPageWidgetExtensionFactory que nous enregistrons à l'aide de Qt Widgets Designer's current extension manager récupéré à partir du paramètre QDesignerFormEditorInterface. Le premier argument est la fabrique nouvellement créée et le second est un identifiant d'extension qui est une chaîne de caractères. La macro Q_TYPEID() convertit simplement la chaîne en QLatin1String.

La classe MultiPageWidgetExtensionFactory est une sous-classe de QExtensionFactory. Lorsque Qt Widgets Designer doit savoir si un widget est un conteneur ou non, le gestionnaire d'extension de Qt Widgets Designer passe en revue toutes les usines enregistrées et invoque la première qui est en mesure de créer une extension de conteneur pour ce widget. Cette usine créera à son tour un objet MultiPageWidgetExtension.

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;
}

Enfin, jetez un coup d'œil à la fonction domXml(). Cette fonction inclut les paramètres par défaut du widget dans le format XML standard utilisé par Qt Widgets Designer. Dans ce cas, nous spécifions la première page du conteneur ; toutes les pages initiales d'un widget multipage doivent être spécifiées dans cette fonction.

Définition de la classe MultiPageWidgetExtensionFactory

La classe MultiPageWidgetExtensionFactory hérite de QExtensionFactory qui fournit une usine d'extension standard pour Qt Widgets Designer.

class MultiPageWidgetExtensionFactory: public QExtensionFactory
{
    Q_OBJECT

public:
    explicit MultiPageWidgetExtensionFactory(QExtensionManager *parent = nullptr);

protected:
    QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const override;
};

L'objectif de la sous-classe est de réimplémenter la fonction QExtensionFactory::createExtension(), ce qui lui permet de créer une extension de conteneur MultiPageWidget.

Mise en œuvre de la classe MultiPageWidgetExtensionFactory

Le constructeur de la classe appelle simplement le constructeur de la classe de base QExtensionFactory:

MultiPageWidgetExtensionFactory::MultiPageWidgetExtensionFactory(QExtensionManager *parent)
    : QExtensionFactory(parent)
{}

Comme décrit ci-dessus, la fabrique est invoquée lorsque Qt Widgets Designer doit savoir si le widget associé est un conteneur ou non.

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 DesignerLe comportement de est le même que l'extension demandée soit associée à un conteneur, à une feuille de membre, à une feuille de propriété ou à un menu de tâches : Son gestionnaire d'extensions parcourt toutes les usines d'extensions enregistrées en appelant createExtension() pour chacune d'entre elles jusqu'à ce que l'une d'entre elles réponde en créant l'extension demandée.

Ainsi, la première chose que nous faisons dans MultiPageWidgetExtensionFactory::createExtension() est de vérifier si l'objet QObject, pour lequel l'extension est demandée, est en fait un objet MultiPageWidget. Nous vérifions ensuite si l'extension demandée est une extension de conteneur.

Si l'objet est un MultiPageWidget demandant une extension de conteneur, nous créons et renvoyons un objet MultiPageWidgetExtension. Dans le cas contraire, nous renvoyons simplement un pointeur nul, ce qui permet au gestionnaire d'extensions de Qt Widgets Designer de poursuivre sa recherche parmi les usines enregistrées.

Définition de la classe MultiPageWidgetContainerExtension

La classe MultiPageWidgetContainerExtension hérite de QDesignerContainerExtension, qui permet d'ajouter (et de supprimer) des pages à un plugin de conteneur multipage dans Qt Widgets Designer.

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;
};

Il est important de reconnaître que la classe QDesignerContainerExtension n'est destinée qu'à fournir un accès Qt Widgets Designer à la fonctionnalité de votre widget multi-page personnalisé ; votre widget multi-page personnalisé doit implémenter la fonctionnalité correspondant aux fonctions de l'extension.

Notez également que nous implémentons un constructeur qui prend deux arguments : le widget parent et l'objet MultiPageWidget pour lequel le menu des tâches est demandé.

QDesignerContainerExtension L'extension fournit par défaut quelques entrées de menu dans le menu des tâches de Qt Widgets Designer, permettant à l'utilisateur d'ajouter ou de supprimer des pages au widget multipage personnalisé associé dans l'espace de travail de Qt Widgets Designer.

Mise en œuvre de la classe MultiPageWidgetContainerExtension

Dans le constructeur, nous enregistrons la référence à l'objet MultiPageWidget envoyé en paramètre, c'est-à-dire le widget associé à l'extension. Nous en aurons besoin ultérieurement pour accéder au widget multipage personnalisé qui effectue les actions demandées.

MultiPageWidgetContainerExtension::MultiPageWidgetContainerExtension(MultiPageWidget *widget,
                                                                     QObject *parent)
    : QObject(parent)
    , myWidget(widget)
{
}

Pour permettre à Qt Widgets Designer de gérer et de manipuler votre widget multipage personnalisé, vous devez réimplémenter toutes les fonctions de QDesignerContainerExtension:

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();
}

Vous devez réimplémenter canAddWidget() et addWidget() qui ajoutent une page donnée au conteneur, count() qui renvoie le nombre de pages dans le conteneur et currentIndex() qui renvoie l'index de la page actuellement sélectionnée.

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);
}

Vous devez réimplémenter insertWidget() ajoutant une page donnée au conteneur à un index donné, canRemove() et remove() supprimant la page à un index donné, setCurrentIndex() définissant l'index de la page actuellement sélectionnée, et enfin widget() renvoyant la page à un index donné.

Définition de la classe MultiPageWidget

La classe MultiPageWidget est un widget conteneur personnalisé qui permet à l'utilisateur de manipuler et de remplir ses pages, et de naviguer entre elles à l'aide d'une boîte combinée.

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;
};

Le principal détail à observer est que votre widget multipage personnalisé doit mettre en œuvre des fonctionnalités correspondant aux fonctions membres de la classe QDesignerContainerExtension, puisque la classe QDesignerContainerExtension n'est destinée qu'à fournir un accès Qt Designer aux fonctionnalités de votre widget multipage personnalisé.

En outre, nous déclarons les propriétés currentIndex et pageTitle, ainsi que les fonctions set et get qui leur sont associées. En déclarant ces attributs en tant que propriétés, nous permettons à Qt Widgets Designer de les gérer de la même manière qu'il gère les propriétés dont le widget MultiPageWidget hérite de QWidget et QObject, par exemple en mettant en avant l'éditeur de propriétés.

Notez l'attribut STORED dans la déclaration de la propriété pageTitle: L'attribut STORED indique la persistance, c'est-à-dire qu'il déclare si la valeur de la propriété doit être mémorisée lors du stockage de l'état d'un objet. Comme indiqué plus haut, nous avons choisi de stocker le titre de la page à l'aide de la propriété QWidget::windowTitle afin de pouvoir donner à chaque page son propre titre. C'est pourquoi la propriété pageTitle est une "fausse" propriété, fournie à des fins d'édition, et n'a pas besoin d'être stockée.

Nous devons également implémenter et émettre les signaux currentIndexChanged() et pageTitleChanged() pour nous assurer que l'éditeur de propriétés de Qt Widgets Designer est mis à jour chaque fois que l'utilisateur consulte une autre page ou modifie l'un des titres de la page.

Voir l'implémentation de la classe MultiPageWidget dans containerextension/multipagewidget.cpp pour plus de détails.

Exemple de projet @ code.qt.io

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