Developpez.com - Qt
X

Choisissez d'abord la catégorieensuite la rubrique :

Viadeo Twitter Facebook Share on Google+   
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Toutes les fonctions  ·  Vues d'ensemble  · 

Étendre QML en C++

La syntaxe du QML décrit déclarativement comment construire un arbre d'objets en mémoire. Dans Qt, QML est principalement utilisé pour décrire une scène visuelle mais n'est pas conceptuellement limité à cela : le format QML est une description abstraite d'un arbre d'objets. Tous les éléments QML inclus dans Qt sont implémentés en utilisant les mécanismes d'extension du QML à partir du C++ décrits dans cette page. Les programmeurs peuvent utiliser ces bibliothèques pour ajouter de nouveaux types qui interagissent avec les types Qt existants ou pour adapter QML à un usage différent de celui prévu.

Ajouter des types

 import People 1.0
 
 Person {
     name: "Bob Jones"
     shoeSize: 12
 }

L'exemple ci-dessus de QML instancie une personne Person et définit les propriétés de nom name et de taille de chaussure shoeSize. Tout en QML revient à instancier un objet ou affecter une valeur.

Le QML s'appuie fortement sur le système de métaobjets de Qt et ne peut instancier que les classes qui dérivent de QObject. Pour les éléments visuels, cela est normalement fait en créant des sous-classes de QDeclarativeItem ; pour les modèles utilisés avec les éléments de la vue, des sous-classes de QAbstractItemModel ; et pour les objets arbitraires possédant des propriétés, des sous-classes directes de QObject.

Le moteur QML n'a aucune connaissance intrinsèque des classes. À la place, le programmeur doit enregistrer les types C++ avec leur nom QML correspondant.

Les types C++ personnalisés sont enregistrés en utilisant une fonction template :

 template<typename T>
 int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)

L'appel à la fonction qmlRegisterType() enregistre le type C++ T dans le système QML et le rend disponible en QML sous le nom qmlName dans la bibliothèque uri en version versionMajor.versionMinor. Le qmlName peut être le même que le nom du type C++.

Le type T doit être un type concret héritant de QObject et possédant un constructeur par défaut.

#include <QtDeclarative> pour utiliser qmlRegisterType().

Les types peuvent être enregistrés par des bibliothèques, du code applicatif ou par des plug-ins (voir QDeclarativeExtensionPlugin).

Une fois l'enregistrement effectué, toutes les propriétés des types connus sont disponibles en QML. QML connaît intrinsèquement les propriétés des types listés dans le document ajout de propriétés, qui inclut les types suivants :

Lorsqu'une propriété d'un type connu est ajoutée à une classe C++, l'élément QML basé sur cette classe aura un gestionnaire de signal value-changed. Voir support des signaux ci-dessous.

QML bénéficie de ce qu'on appelle un typage sûr (il est typesafe). Si vous tentez d'affecter une valeur invalide à une propriété, la propriété génèrera une erreur. Par exemple, prenons la propriété nom (name) de l'élément personne (Person) ayant pour type QString, ce code causerait une erreur :

 Person {
     // Ne fonctionnera pas
     name: 12
 }

Étendre le QML - exemple d'ajout de types présente un code complet utilisé pour créer le type Person.

Les propriétés de type objet et liste

 BirthdayParty {
     host: Person {
         name: "Bob Jones"
         shoeSize: 12
     }
     guests: [
         Person { name: "Leo Hodges" },
         Person { name: "Jack Smith" },
         Person { name: "Anne Brown" }
     ]
 }

L'exemple de QML ci-dessus affecte un objet Person à la propriété hôte host de BirthdayParty et affecte trois objets Person comme invités à la propriété guests.

QML peut définir des propriétés plus complexes que les types basiques intrinsèques tels que les entiers et les chaînes de caractères. Les propriétés peuvent aussi être des pointeurs sur des objets, des pointeurs sur des interfaces Qt, des listes de points et des listes de pointeurs sur des interfaces Qt. Comme le QML est typesafe il garantit que seuls des types valides sont affectés à ces propriétés, tout comme il le fait avec les types primitifs.

Les propriétés qui sont des pointeurs sur des objets ou sur des interfaces Qt sont déclarées avec la macro Q_PROPERTY(), tout comme les autres propriétés. La déclaration de la propriété hôte host est la suivante :

     Q_PROPERTY(Person *host READ host WRITE setHost)

Tant que la propriété de type, dans ce cas Person, est enregistrée dans QML, la propriété peut être affectée.

QML permet aussi l'affectation d'interfaces Qt. Pour affecter une propriété dont le type est un pointeur sur une interface Qt, l'interface doit aussi être enregistrée dans QML. Comme elles ne peuvent pas être instanciées directement, l'enregistrement d'une interface Qt est différent de l'enregistrement d'un nouveau type QML. La fonction suivante est utilisée à la place :

 template<typename T>
 int qmlRegisterInterface(const char *typeName)

Cela enregistre l'interface C++ T dans le système QML comme typeName.

Après l'enregistrement, QML peut forcer des objets implémentant cette interface pour des affectations à des propriétés de types appropriés.

La propriété guests est une liste d'objets Person. Les propriétés qui sont des listes d'objets ou d'interfaces Qt sont aussi déclarées avec la macro Q_PROPERTY(), tout comme les autres propriétés. Les propriétés de listes doivent avoir le type QDeclarativeListProperty<T>. Comme pour les propriétés objets, le type T doit être enregistré dans QML.

La déclaration de la propriété guest ressemble à ceci :

     Q_PROPERTY(QDeclarativeListProperty<Person> guests READ guests)

Étendre QML - exemple de propriétés de type objet et liste présente le code complet utilisé pour créer le type BirthdayParty.

Héritage et forçage

 BirthdayParty {
     host: Boy {
         name: "Bob Jones"
         shoeSize: 12
     }
     guests: [
         Boy { name: "Leo Hodges" },
         Boy { name: "Jacck Smith" },
         Girl { name: "Anne Brown" }
     ]
 }

L'exemple de code QML ci-dessus affecte l'objet Boy à la propriété hôte (host) de BirthdayParty et affecte trois autres objets à la propriété invités (guests).

QML gère les hiérarchies d'héritage du C++ et peut librement effectuer des forçages entre des types d'objets valides et connus. Cela permet la création de classes de base communes autorisant l'affectation de classes spécialisées aux propriétés de types objet ou liste. Dans l'exemple ci-dessus, les deux propriétés hôte (host) et invités (guests) conservent le type Person utilisé dans la section précédente mais l'affection est valide car les objets Boy et Girl héritent de Person.

Pour affecter une valeur à une propriété, le type de la propriété doit être enregistré dans QML. Les deux fonctions templates qmlRegisterType() et qmlRegisterInterface() présentées précédemment peuvent être utilisées pour enregistrer un type dans QML. De plus, si un type agissant purement comme une classe de base qui ne peut pas être instanciée dans QML, il a besoin d'être enregistré, la fonction suivante peut être utilisée :

     template<typename T>
     int qmlRegisterType()

Cela enregistre le type C++ T dans le système QML. L'appel sans paramètre de la fonction template qmlRegisterType() ne définit pas de correspondance entre la classe C++ et le nom d'élément QML, donc il n'est pas possible de créer un élément de ce type dans QML, mais il est utilisable pour le forçage de type.

Le type T doit hériter de QObject mais il n'y a aucune restriction sur le fait qu'il soit concret ou sur la signature de son constructeur.

QML forcera automatiquement les types C++ lors de l'affectation à une propriété objet ou à une propriété liste. Une erreur d'affectation apparaîtra uniquement si le forçage échoue.

Étendre le QML - exemple d'héritage et de forçage montre le code complet utilisé pour créer les types Boy et Girl.

Propriété par défaut

 BirthdayParty {
     host: Boy {
         name: "Bob Jones"
         shoeSize: 12
     }
 
     Boy { name: "Leo Hodges" }
     Boy { name: "Jack Smith" }
     Girl { name: "Anne Brown" }
 }

Le code QML ci-dessus montre l'affectation d'une collection d'objets à la propriété par défaut de BirthdayParty.

La propriété par défaut est une commodité syntaxique permettant au concepteur d'un type de spécifier une propriété unique comme propriété par défaut du type. La propriété par défaut reçoit les affectations dans les cas où la propriété à affecter n'est pas spécifiée explicitement. Le comportement est identique à l'affectation explicite de la propriété par son nom.

Depuis C++, le développeur marque la propriété par défaut en utilisant une annotation Q_CLASSINFO():

 Q_CLASSINFO("DefaultProperty", "property")

Cela marque la propriété property comme propriété par défaut de la classe. La propriété property doit être soit une propriété objet, soit une propriété liste.

La déclaration d'une propriété par défaut est optionnelle. Une classe dérivée hérite de la propriété par défaut de la classe de base mais peut la surcharger dans sa propre déclaration. La propriété property peut faire référence à une propriété déclarée dans la classe ou à une propriété héritée de la classe de base.

Étendre le QML - exemple de propriété par défaut montre le code complet utilisé pour spécifier une propriété par défaut.

Propriétés groupées

     Boy {
         name: "Jack Smith"
         shoe {
             size: 8
             color: "blue"
             brand: "Puma"
             price: 19.95
         }
     }

Le code QML ci-dessus attribue plusieurs propriétés à l'objet Boy, incluant quatre propriétés utilisant la syntaxe des propriétés groupées.

Les propriétés groupées rassemblent plusieurs propriétés similaires en un seul bloc nommé. Les propriétés groupées peuvent être utilisées pour présenter une interface plus agréable aux développeurs et peut aussi simplifier l'implémentation de collections de propriétés communes à différents types grâce à la réutilisation de l'implémentation.

Un bloc de propriétés groupées est implémenté sous forme d'une propriété objet en lecture seule. La propriété chaussure shoe présentée dans l'exemple de code est déclarée comme suit :

     Q_PROPERTY(ShoeDescription *shoe READ shoe)

Le type ShoeDescription déclare les propriétés disponibles pour le bloc de propriétés groupées - dans ce cas, les propriétés de taille size, de couleur color, de marque brand et de prix price.

Les blocs de propriétés groupées peuvent être déclarés et accédés récursivement.

Étendre le QML - exemple de propriétés groupées présente le code complet utilisé pour implémenter le groupe de propriétés shoe.

Propriétés attachées

     Boy {
         name: "Leo Hodges"
         shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 }
 
         BirthdayParty.rsvp: "2009-07-06"
     }

Le code QML ci-dessus affecte une date à la propriété rsvp en utilisant la syntaxe de propriété attachée.

Les propriétés attachées permettent à des types d'ajouter des propriétés à d'autres types avec lesquels ils n'ont pas de relation, généralement pour leur propre usage. Les propriétés attachées sont identifiées par l'utilisation du nom du type créateur de l'attache, dans le cas présent BirthdayParty, comme préfixe au nom de propriété.

Dans l'exemple ci-dessus, BirthdayParty est appelé le type attacheur ; l'instance Boy, l'objet receveur.

Pour le type attacheur, un bloc de propriétés attachées est implémenté comme un nouveau type dérivant de QObject, appelé objet d'attachement. Les propriétés de l'objet d'attachement sont celles qui deviennent disponibles comme bloc de propriétés attachées.

N'importe quel type QML peut devenir un type attacheur en déclarant la fonction publique qmlAttachedProperties() et en déclarant l'information de type QML_HAS_ATTACHED_PROPERTIES:

 class MyType : public QObject {
     Q_OBJECT
 public:
 
     ...
 
     static AttachedPropertiesType *qmlAttachedProperties(QObject *object);
 };
 
 QML_DECLARE_TYPEINFO(MyType, QML_HAS_ATTACHED_PROPERTIES)

La fonction retourne un objet d'attachement, du type AttachedPropertiesType, pour l'objet receveur object. Il est d'usage, mais pas strictement obligatoire, que l'objet d'attachement ait comme parent l'objet object afin d'éviter les fuites de mémoire.

Le type AttachedPropertiesType doit être un type dérivé de QObject. Les propriétés de ce type vont être accessibles grâce à la syntaxe des propriétés attachées.

Cette méthode va être appelée au moins une fois pour chaque objet attaché. Le moteur QML mettra en cache le pointeur retourné pour les prochains accès à la propriété. Par conséquent, l'objet d'attachement ne peut pas être détruit tant que l'objet object n'est pas détruit.

Dans le principe, les propriétés attachées sont un type exportant un ensemble de propriétés additionnelles qui peuvent être définies dans n'importe quel autre objet. Les propriétés attachées ne peuvent pas être limitées à l'attachement à un sous-ensemble d'objets, bien que leurs effets puissent être limités à ce sous-ensemble.

Par exemple, un scénario courant est d'utiliser un type pour étendre les propriétés disponibles pour ses enfants afin de récupérer des données spécifiques à l'instance. Ici nous ajoutons un champ rsvp pour tous les invités venant à une fête d'anniversaire :

 BirthdayParty {
     Boy { BirthdayParty.rsvp: "2009-06-01" }
 }

Cependant, comme un type ne peut pas limiter les instances auxquelles l'objet d'attachement doit s'attacher, le code suivant est aussi permis, même si l'ajout d'une date de fête d'anniversaire dans ce contexte n'a aucun intérêt.

 GraduationParty {
     Boy { BirthdayParty.rsvp: "2009-06-01" }
 }

Depuis C++, y compris depuis l'implémentation du type attacheur, on peut accéder à l'objet d'attachement d'une instance en utilisant la méthode suivante :

 template<typename T>
 QObject *qmlAttachedPropertiesObject<T>(QObject *attachee, bool create = true);

La fonction retourne l'objet d'attachement attaché à attachee (le receveur) par le type attacheur T. Si le type T n'est pas un type attacheur valide, la méthode retourne toujours 0.

Si create est défini à true, un objet d'attachement valide sera toujours retourné, et il sera créé s'il n'existe pas déjà. Si create est défini à false, l'objet d'attachement va être retourné seulement s'il a été créé précédemment.

Étendre le QML - Exemple de propriétés attachées montre le code complet utilisé pour implémenter la propriété rsvp attachée.

Gestion de la mémoire et type QVariant

Il est de la responsabilité de l'élément de s'assurer qu'il n'accède pas ou ne retourne pas de pointeur sur des objets invalides. QML fournit les garanties suivantes.

  • Un objet affecté à une propriété pointeur sur un QObject (ou sur un objet dérivé de QObject) sera valide au moment de l'affectation.

Après l'affectation, il est de la responsabilité de la classe de suivre la validité de ce pointeur, soit par une méthode spécifique de la classe, soit par la classe générique QPointer.

  • Un objet affecté à un QVariant sera valide au moment de l'affectation.

Lors de l'affectation d'un objet à une propriété QVariant, QML utilisera toujours un QVariant de type QMetaType::QObjectStar. Il est de la responsabilité de la classe de suivre la validité de ce pointeur. Une règle générale lors de l'écriture d'une classe utilisant des propriétés QVariant est de vérifier le type du QVariant lorsqu'il est affecté, et si le type n'est pas géré par votre classe, de réaffecter un QVariant invalide.

  • Un objet affecté à une propriété liste de QObject (ou de dérivés de QObject) sera toujours valide au moment de l'affectation.

Après affectation, il est de la responsabilité de la classe de suivre la validité de ce pointeur, soit par une méthode spécifique de la classe, soit par la classe générique QPointer.

Les éléments doivent considérer que n'importe quel objet QML affecté peut être détruit à tout moment, et réagir en conséquence. À condition de le documenter, un élément peut ne plus fonctionner dans cette situation, mais il ne doit ne pas crasher.

Gestion des signaux

 BirthdayParty {
     onPartyStarted: console.log("This party started rockin' at " + time);
 }

Le code QML ci-dessus associe l'évaluation d'une expression JavaScript avec l'émission d'un signal Qt.

Tous les signaux Qt d'une classe enregistrée deviennent disponibles comme « propriétés signal » spéciales dans QML, des propriétés auxquelles l'utilisateur peut affecter une expression JavaScript unique. Le nom de la propriété signal est une version transformée du nom du signal de Qt: « on » est ajouté au début et la première lettre du nom du signal est mise en majuscule. Par exemple, le signal utilisé dans l'exemple ci-dessus possède la signature C++ suivante :

 signals:
     void partyStarted(const QTime &time);

Dans les classes possédant de multiples signaux avec le même nom, seul le signal final est accessible comme propriété signal. Notez que les signaux avec le même nom mais des paramètres différents ne peuvent être distingués.

Les paramètres du signal deviennent accessibles par leur nom dans le script affecté. Un paramètre non nommé ne peut être accédé, prenez donc soin de donner un nom à tous les paramètres du signal dans la déclaration C++. Les types intrinsèques listés dans ajouter des types, ainsi que les types d'objets enregistrés sont acceptés comme types de paramètre de signal. L'utilisation d'autres types n'est pas une erreur mais la valeur du paramètre ne sera pas accessible à partir du script.

Étendre le QML - l'exemple du support des signaux montre le code complet utilisé pour implémenter la propriété signal onPartyStarted.

Si vous souhaitez utiliser les signaux à partir d'éléments créés en dehors de QML, vous pouvez accéder à leurs signaux par le biais de l'élément Connections.

De plus, si une propriété est ajoutée à la classe C++, tous les éléments QML basés sur cette classe auront un gestionnaire de signal value-changed pour cette propriété. Le nom du gestionnaire de signal est on<nom-de-la-propriété>Changed, avec la première lettre du nom de la propriété en majuscule.

Note : le gestionnaire de signal QML sera toujours nommé on<nom-de-la-propriété>Changed, sans tenir compte du nom utilisé pour le signal NOTIFY en C++. Nous recommandons l'utilisation de <nom-de-la-propriété>Changed() pour le signal NOTIFY en C++.

Voir aussi écriture de composants QML : propriétés, méthodes et signaux

Méthodes

Les slots et méthodes marqués Q_INVOKABLE deviennent des fonctions pouvant être appelées depuis QML.

 BirthdayParty {
     host: Person {
         name: "Bob Jones"
         shoeSize: 12
     }
     guests: [
         Person { name: "Leo Hodges" },
         Person { name: "Jack Smith" },
         Person { name: "Anne Brown" }
     ]
 
     Component.onCompleted: invite("William Green")
 }

Dans cet exemple, une invitation est ajoutée via la méthode invite() de l'élément BirthdayParty. Cette fonction est rendue accessible en QML en marquant la méthode invite() avec Q_INVOKABLE dans la classe BirthdayParty:

     Q_INVOKABLE void invite(const QString &name);

Étendre le QML - Exemple de méthodes montre le code complet utilisé pour implémenter la méthode invite() .

La méthode invite() est également rendue accessible si elle est déclarée comme slot.

Sources de valeur de propriété

 BirthdayParty {
     HappyBirthdaySong on announcement { name: "Bob Jones" }
 }

Le code QML ci-dessus applique une source de valeur de propriété à la propriété announcement. Une source de valeur de propriété génère une valeur de propriété changeant au fil du temps.

Les sources de valeur de propriété sont souvent utilisées pour effectuer une animation. Plutôt que de construire un objet et de définir manuellement la propriété « cible » de l'animation, une source de valeur de propriété peut être affectée directement à une propriété de n'importe quel type et créer directement cette association.

L'exemple montré ici est assez artificiel : la propriété « annonce » (announcement) de l'objet BirthdayParty est une chaine de caractères qui est affichée à chaque fois qu'elle reçoit une affectation et la valeur source HappyBirthdaySong génère les paroles de la chanson « Happy Birthday ».

     Q_PROPERTY(QString announcement READ announcement WRITE setAnnouncement)

Normalement, l'affectation d'un objet à une propriété de chaine de caractères n'est pas permise. Dans le cas de la source de valeur de propriété, plutôt que d'affecter l'instance de l'objet elle-même, le moteur QML définit une association entre la valeur source et la propriété.

Les sources de valeur de propriété sont des types spéciaux qui dérivent de la classe QDeclarativePropertyValeurSource. Cette classe contient une seule méthode, QDeclarativePropertyValeurSource::setTarget(), que le moteur QML invoque lors de l'association de la source de valeur de propriété à une propriété. La partie importante de la déclaration du type HappyBirthdaySong est :

 class HappyBirthdaySong : public QObject, public QDeclarativePropertyValeurSource
 {
     Q_OBJECT
     Q_INTERFACES(QDeclarativePropertyValeurSource)
 public:
     HappyBirthdaySong(QObject *parent = 0);
 
     virtual void setTarget(const QDeclarativeProperty &);
 };

À tous les autres égards, les sources de valeur de propriété sont des types QML normaux. Ils doivent être enregistrés dans le moteur QML en utilisant les mêmes macros que les autres types et peuvent contenir des propriétés, signaux et méthodes à l'identique des autres types.

Lorsqu'une source de valeur de propriété est affectée à une propriété, QML essaie d'abord de l'affecter normalement, comme pour un type QML habituel. C'est seulement dans le cas où cette affectation échoue que le moteur appelle la méthode setTarget(). Cela permet au type d'être aussi utilisé dans d'autres contextes que celui des valeurs source.

Étendre le QML - l'exemple de Property value Source montre le code complet de l'implémentation de la source de valeur de propriété HappyBirthdaySong.

Liaison de propriété

 BirthdayParty {
     id: theParty
 
     HappyBirthdaySong on announcement { name: theParty.host.name }
 
     host: Boy {
         name: "Bob Jones"
         shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
     }
 }

Le code QML ci-dessus utilise une liaison de propriété pour s'assurer que la propriété nom (name) de HappyBirthdaySong reste égale à celle de l'hôte (host).

La liaison de propriété est une fonctionnalité maîtresse de QML. En plus d'affecter des valeurs littérales, la liaison de propriété permet au développeur d'affecter une expression JavaScript complexe qui peut inclure des dépendances à d'autres propriétés. À chaque changement du résultat de l'expression - à travers le changement de l'une des valeurs de l'expression - l'expression est automatiquement réévaluée et le nouveau résultat est affecté à la propriété.

Toutes les propriétés des types personnalisés gèrent automatiquement la liaison de propriété. Toutefois, afin que la liaison fonctionne correctement, QML doit être capable de déterminer de manière fiable qu'une propriété a été modifiée, pour savoir quand réévaluer les liaisons dépendant de cette valeur. QML compte sur la présence du signal NOTIFY pour cette détermination.

Voici la déclaration de la propriété hôte host :

     Q_PROPERTY(Person *host READ host WRITE setHost NOTIFY hostChanged)

L'attribut NOTIFY est suivi par un nom de signal. Il est de la responsabilité du créateur de la classe de s'assurer qu'à chaque fois que la valeur change, le signal NOTIFY est émis. La signature du signal NOTIFY n'est pas importante pour QML.

Afin d'éviter les boucles ou les évaluations excessives, les développeurs doivent s'assurer que le signal n'est émis que lorsque la valeur est réellement modifiée. Si une propriété ou un groupe de propriétés sont rarement utilisés, il est permis d'utiliser le même signal NOTIFY pour plusieurs propriétés. Cela doit être effectué avec précaution pour éviter une dégradation des performances.

Pour que QML reste fiable, si la propriété ne possède pas de signal NOTIFY, elle ne pourra pas être utilisée comme expression de liaison. Cependant, la propriété peut toujours recevoir une affectation à une liaison car QML n'a pas besoin de surveiller les changements de cette propriété dans ce scénario.

Supposez un type personnalisé, TestElement, possédant deux propriétés, « a » et « b ». La propriété « a » n'a pas de signal NOTIFY et la propriété « b » a un signal NOTIFY.

 TestElement {
     // Cela est correct
     a: b
 }
 TestElement {
     // Cela ne fonctionnera pas
     b: a
 }

La présence d'un signal NOTIFY a un léger impact sur les performances. Dans certains cas la valeur de la propriété est définie à la construction de l'objet, et ne change plus par la suite. Le plus courant de ces cas est lorsqu'un type utilise les propriétés groupées et que le groupe est alloué une seule fois et n'est libéré que lors de la destruction de l'objet. Dans ces cas, l'attribut CONSTANT peut être ajouté à la déclaration de la propriété à la place d'un signal NOTIFY.

     Q_PROPERTY(ShoeDescription *shoe READ shoe CONSTANT)

Ce cas doit faire l'objet d'un soin particulier car les applications utilisant votre type pourraient mal se comporter. L'attribut CONSTANT doit seulement être utilisé pour les propriétés dont les valeurs sont définies (et finalisées) uniquement dans le constructeur de classe. Toutes les autres propriétés pouvant être utilisées dans des liaisons doivent à la place posséder un signal NOTIFY.

Étendre le QML - l'exemple de liaison présente l'exemple BirthdayParty mis à jour pour inclure des signaux NOTIFY pour une utilisation dans des liaisons.

Les objets d'extension

 QLineEdit {
     leftMargin: 20
 }

Le code QML ci-dessus ajoute une nouvelle propriété à un type C++ existant sans modifier son code source.

Lors de l'intégration de classes et de technologies existantes dans QML, leurs interfaces auront souvent besoin d'être ajustées pour mieux s'adapter à l'environnement déclaratif. Bien que les meilleurs résultats soient normalement obtenus en modifiant directement les classes originales, si cela n'est pas possible ou trop compliqué à cause d'autres contraintes, les objets d'extension permettent des extensions limitées sans modification directe.

Les objets d'extension sont utilisés pour ajouter des propriétés additionnelles à un type existant. Vous ne pouvez ajouter que des propriétés. Une définition de type étendue permet au programmeur de fournir un type additionnel - appelé le type d'extension - lors de l'enregistrement d'une classe cible. Ces propriétés sont fusionnées avec la classe de base et peuvent être utilisées à partir de QML.

Une classe d'extension est un QObject normal, ayant un constructeur qui prend un pointeur sur QObject. Au moment où cela est nécessaire (la création d'une classe d'extension est retardée jusqu'au premier accès à une propriété étendue) la classe d'extension est créée et l'objet cible est passé au constructeur comme parent. Lors de l'accès à une propriété étendue de l'objet original, la propriété correspondante de l'objet étendu est utilisée à sa place.

Lorsqu'un type étendu est défini, l'une de ces fonctions :

 template<typename T, typename ExtendedT>
 int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
 
 template<typename T, typename ExtendedT>
 int qmlRegisterExtendedType()

doit être utilisée à la place des variations de qmlRegisterType(). Les arguments sont les mêmes que pour les fonctions sans extension correspondantes, sauf pour le paramètre ExtendedT qui décrit le type de l'objet d'extension.

Optimisation

Pour développer des éléments à hautes performances, il est souvent utile d'en savoir plus sur l'état du moteur QML. Par exemple, il peut être bénéfique d'effectuer l'initialisation de structure de données coûteuses après la fin de l'initialisation de toutes les propriétés.

Le moteur QML définit une classe d'interface appelée QDeclarativeParserStatus, qui contient plusieurs méthodes virtuelles appelées à des moments divers de l'instanciation du composant. Pour recevoir ces notifications, l'implémentation d'un élément doit hériter de QDeclarativeParserStatus et doit informer le système méta de Qt en utilisant la macro Q_INTERFACES().

Par exemple,

 class Example : public QObject, public QDeclarativeParserStatus
 {
     Q_OBJECT
     Q_INTERFACES(QDeclarativeParserStatus)
 public:
     virtual void componentComplete()
     {
         qDebug() << "Woohoo!  Now to do my costly initialization";
     }
 };

Remerciements

Merci à Alexandre Laurent pour la traduction ainsi qu'à Ilya Diallo, Jonathan Courtois, Thibaut Cuvelier et Claude Leloup pour leur relecture !

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 4.7
Copyright © 2018 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur, une redirection cassée ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
Responsable bénévole de la rubrique Qt : Thibaut Cuvelier -