Sur cette page

Créer des types Qt personnalisés

Vue d'ensemble

Lors de la création d'interfaces utilisateur avec Qt, en particulier celles qui comportent des contrôles et des fonctions spécialisés, les développeurs doivent parfois créer de nouveaux types de données qui peuvent être utilisés parallèlement ou à la place de l'ensemble existant de types de valeurs de Qt.

Les types standard tels que QSize, QColor et QString peuvent tous être stockés dans les objets QVariant, utilisés comme types de propriétés dans les classes basées sur QObject et émis dans la communication par fente de signal.

Dans ce document, nous prenons un type personnalisé et décrivons comment l'intégrer dans le modèle d'objet de Qt afin qu'il puisse être stocké de la même manière que les types Qt standard. Nous montrons ensuite comment enregistrer le type personnalisé pour lui permettre d'être utilisé dans les connexions de signaux et de slots.

Création d'un type personnalisé

Avant de commencer, nous devons nous assurer que le type personnalisé que nous créons répond à toutes les exigences imposées par QMetaType. En d'autres termes, il doit fournir

  • un constructeur public par défaut,
  • un constructeur de copie public, et
  • un destructeur public.

La définition de la classe Message suivante inclut ces membres :

class Message
{
public:
    Message() = default;
    ~Message() = default;
    Message(const Message &) = default;
    Message &operator=(const Message &) = default;

    Message(const QString &body, const QStringList &headers);

    QStringView body() const;
    QStringList headers() const;

private:
    QString m_body;
    QStringList m_headers;
};

La classe fournit également un constructeur pour une utilisation normale et deux fonctions membres publiques qui sont utilisées pour obtenir les données privées.

Déclaration du type avec QMetaType

La classe Message n'a besoin que d'une implémentation appropriée pour être utilisable. Cependant, le système de type de Qt Assistant ne sera pas en mesure de comprendre comment stocker, récupérer et sérialiser les instances de cette classe sans une certaine aide. Par exemple, nous ne pourrons pas stocker les valeurs de Message dans QVariant.

La classe de Qt XML responsable des types personnalisés est QMetaType. Pour faire connaître le type à cette classe, nous invoquons la macro Q_DECLARE_METATYPE() sur la classe dans le fichier d'en-tête où elle est définie :

Q_DECLARE_METATYPE(Message);

Il est ainsi possible de stocker les valeurs Message dans des objets QVariant et de les récupérer ultérieurement :

QVariant stored ; stored.setValue(message) ; ... Message retrieved =  qvariant_cast<Message>(stored) ;qDebug() << "Retrieved:" << retrieved;
retrieved =  qvariant_cast<Message>(stored) ;qDebug() << "Retrieved:" << retrieved;

La macro Q_DECLARE_METATYPE() permet également d'utiliser ces valeurs en tant qu'arguments de signaux, mais uniquement dans le cadre de connexions directes signal-emplacement. Pour rendre le type personnalisé généralement utilisable avec le mécanisme de signaux et d'emplacements, nous devons effectuer quelques travaux supplémentaires.

Création et destruction d'objets personnalisés

Bien que la déclaration de la section précédente rende le type disponible pour une utilisation dans les connexions directes entre signaux et slots, il ne peut pas être utilisé pour les connexions entre signaux et slots en file d'attente, telles que celles qui sont établies entre les objets de différents threads. En effet, le système de méta-objets ne sait pas comment gérer la création et la destruction des objets du type personnalisé au moment de l'exécution.

Pour permettre la création d'objets au moment de l'exécution, appelez la fonction de modèle qRegisterMetaType() pour l'enregistrer auprès du système de méta-objets. Cette fonction rend également le type disponible pour les communications par tranche de signaux en file d'attente, à condition que vous l'appeliez avant d'établir la première connexion qui utilise le type.

L'exemple de type personnalisé en file d'attente déclare une classe Block qui est enregistrée dans le fichier main.cpp:

int main(int argc, char *argv[]) { QApplication app(argc, argv) ;    ...
    qRegisterMetaType<Block>();
    ... return app.exec() ; }

Ce type est utilisé ultérieurement dans une connexion de type signal-slot dans le fichier window.cpp:

Window::Window(QWidget *parent)
    : QWidget(parent), thread(new RenderThread(this))
{
    ...
    connect(thread, &RenderThread::sendBlock,
            this, &Window::addBlock);
    ...
    setWindowTitle(tr("Queued Custom Type"));
}

Si un type est utilisé dans une connexion en file d'attente sans être enregistré, un avertissement sera affiché sur la console ; par exemple :

QObject::connect: Cannot queue arguments of type 'Block'
(Make sure 'Block' is registered using qRegisterMetaType().)

Rendre le type imprimable

Il est souvent utile de rendre un type personnalisé imprimable à des fins de débogage, comme dans le code suivant :

Message message(body, headers) ;qDebug() << "Original:" << message;

Pour ce faire, on crée un opérateur de flux pour le type, qui est souvent défini dans le fichier d'en-tête de ce type :

QDebug operator<<(QDebug dbg, const Message &message);

L'implémentation du type Message s'efforce de rendre la représentation imprimable aussi lisible que possible :

QDebug operator<<(QDebug dbg, const Message &message)
{
    QDebugStateSaver saver(dbg);
    const QList<QStringView> pieces = message.body().split(u"\r\n", Qt::SkipEmptyParts);
    if (pieces.isEmpty())
        dbg.nospace() << "Message()";
    else if (pieces.size() == 1)
        dbg.nospace() << "Message(" << pieces.first() << ")";
    else
        dbg.nospace() << "Message(" << pieces.first() << " ...)";
    return dbg;
}

La sortie envoyée au flux de débogage peut, bien sûr, être aussi simple ou aussi compliquée que vous le souhaitez. Notez que la valeur renvoyée par cette fonction est l'objet QDebug lui-même, bien qu'il soit souvent obtenu en appelant la fonction membre maybeSpace() de QDebug qui remplit le flux avec des caractères d'espacement pour le rendre plus lisible.

Pour en savoir plus

La documentation sur les macros Q_DECLARE_METATYPE() et les fonctions qRegisterMetaType() contient des informations plus détaillées sur leur utilisation et leurs limites.

L'exemple de type personnalisé en file d'attente montre comment mettre en œuvre un type personnalisé avec les fonctionnalités décrites dans ce document.

Le document Techniques de débogage fournit une vue d'ensemble des mécanismes de débogage décrits ci-dessus.

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