Le système de propriétés de QtQt fournit un système sophistiqué de propriétés semblable à celui qui est mis à disposition par quelques créateurs de compilateurs. Toutefois, comme compilateur et comme bibliothèque indépendante de la plateforme, Qt ne se fonde pas sur les dispositifs non standards de compilateurs comme __property ou [property]. La solution de Qt fonctionne avec n'importe quel compilateur standard de C++ et sous toutes les plateformes supportées par Qt. Elle est basée sur le système de méta-objets qui fournit aussi une communication inter-objets via les signaux et les slots. Conditions de déclaration de propriétésPour déclarer une propriété, utiliser la macro Q_PROPERTY() dans une classe héritant de QObject. Q_PROPERTY(type name READ getFunction [WRITE setFunction] [RESET resetFunction] [NOTIFY notifySignal] [DESIGNABLE bool] [SCRIPTABLE bool] [STORED bool] [USER bool] [CONSTANT] [FINAL]) Voici des exemples typiques de déclarations de propriétés, extraits de QWidget. Q_PROPERTY(bool focus READ hasFocus) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor) Une propriété se comporte comme une donnée de membre d'une classe, mais elle possède des dispositifs additionnels accessibles depuis le système de méta-objets.
Les propriétés READ, WRITE et RESET peuvent être héritées et peuvent aussi être virtuelles. Lorsqu'elles sont héritées dans des classes où l'instanciation multiple est utilisée, elles doivent provenir de la première classe héritée. Le type de propriété peut être n'importe lequel des types supportés par QVariant, ou il peut être un type défini par l'utilisateur. Dans cet exemple, la classe QDate est considérée comme un type défini par l'utilisateur. Q_PROPERTY(QDate date READ getDate WRITE setDate) Parce que QDate est un type défini par l'utilisateur, vous devez inclure le fichier d'en-tête <QDate> avec la déclaration de propriété. Pour les propriétés de QMap, QList et QValueList, la valeur est un QVariant dont la valeur peut être la liste entière ou la map. Notez que la chaîne de caractères de Q_PROPERTY ne peut contenir de virgule, car les virgules séparent les arguments de macros. Par conséquent, vous devez utiliser QMap comme le type de propriété à la place de QMap<QString, QVariant>. Pour la cohérence, utilisez aussi QList et QValueList à la place de QList<QVariant> et QValueList<QVariant>. Propriétés de lecture et d'écriture avec le système de méta-objetsUne propriété peut être lue et écrite par l'utilisation des fonctions génériques QObject::property() et QObject::setProperty(), sans savoir quoique ce soit sur la classe possesseur, excepté le nom de la propriété. Dans l'extrait de code situé ci-dessous, les appels de QAbstractButton::setDown() et de QObject::setProperty() définissent la propriété down. QPushButton *button = new QPushButton; QObject *object = button; button->setDown(true); object->setProperty("down", true); L'accès à une propriété par le biais de son accesseur WRITE est la meilleure des deux solutions car cela représente un moyen plus rapide et car cela donne de meilleurs diagnostics au moment de la compilation, mais la définition d'une propriété de cette manière nécessite ce que vous savez à propos de la classe au moment de la compilation. L'accès aux propriétés par leur nom vous laisse accéder au moment de la compilation aux classes que vous ne connaissez pas. Vous pouvez découvrir une propriété de classe lors de l'exécution par la requête de son QObject, QMetaObject et QMetaProperties. QObject *object = ... const QMetaObject *metaobject = object->metaObject(); int count = metaobject->propertyCount(); for (int i=0; i<count; ++i) { QMetaProperty metaproperty = metaobject->property(i); const char *name = metaproperty.name(); QVariant value = object->property(name); ... } Dans l'extrait ci-dessus, QMetaObject::property() est utilisé pour obtenir des métadonnées à propos de chaque propriété définie dans une certaine classe inconnue. Le nom de la propriété est cherché depuis la métadonnée puis passé au QObject::property() pour obtenir la valeur de la propriété dans l'objet actuel. Un exemple simpleSupposons que nous avons une classe MyClass, dérivée de QObject et utilisant la macro Q_OBJECT dans sa section privée. Nous voulons déclarer une propriété dans MyClass pour garder une trace de la valeur prioritaire. Le nom de cette propriété sera priority, et son type sera une énumération nommée Priority, qui est définie dans MyClass. Nous déclarons la propriété avec la macro Q_PROPERTY() déclarée dans la section privée de la classe. La fonction nécessaire READ est nommée priority, et nous incluons une fonction WRITE nommée setPriority. L'énumération doit être enregistrée avec le système de méta-objets en utilisant la macro Q_ENUMS(). L'enregistrement d'une énumération rend les noms d'énumérateurs disponibles à l'usage pour les appels de QObject::setProperty(). Nous devons aussi fournir nos propres déclarations pour les fonctions READ et WRITE. La déclaration de MyClass doit donc ressembler à cela : class MyClass : public QObject { Q_OBJECT Q_PROPERTY(Priority priority READ priority WRITE setPriority) Q_ENUMS(Priority) public: MyClass(QObject *parent = 0); ~MyClass(); enum Priority { High, Low, VeryHigh, VeryLow }; void setPriority(Priority priority); Priority priority() const; }; La fonction READ est constante et retourne le type de la propriété. La fonction WRITE retourne void et possède exactement un paramètre du type de la propriété. Le compilateur de méta-objets l'impose. Étant donné un pointeur à une instance de MyClass ou un pointeur à une instance de QObject qui s'avère être une instance de MyClass, nous avons deux façons de définir sa propriété de priorité. MyClass *myinstance = new MyClass; QObject *object = myinstance; myinstance->setPriority(MyClass::VeryHigh); object->setProperty("priority", "VeryHigh"); Dans l'exemple, l'énumération utilisée pour le type de la propriété a été localement déclarée dans MyClass. Si elle avait été déclarée dans une autre classe, son nom pleinement qualifié (par exemple, OtherClass::Priority) serait nécessaire. De plus, cette autre classe devrait aussi hériter de QObject et enregistrer son énumération avec Q_ENUMS(). Une macro similaire, Q_FLAGS(), est aussi disponible. Comme Q_ENUMS(), elle enregistre une énumération, mais marque le type comme étant un ensemble de flags (ou drapeaux), ce qui signifie qu'elles peuvent être combinées avec l'opération logique OU. Une classe d'E/S peut avoir des valeurs d'énumération READ et WRITE, et dans ce cas, QObject::setProperty() peut accepter READ | WRITE. Q_FLAGS() devrait être utilisé pour enregistrer cette énumération. Propriétés dynamiquesLa fonction QObject::setProperty() peut aussi être utilisée pour ajouter de nouvelles propriétés à une instance de classe lors de l'exécution. Lorsqu'elle est appelée avec un nom et une valeur, si une propriété avec le nom donné existe dans le QObject et si la valeur donnée est compatible avec le type de la propriété, la valeur est stockée dans la propriété, et true est retourné. Si la valeur n'est pas compatible avec le type de la propriété, la propriété n'est pas changée, et false est retourné. Mais si la propriété avec le nom donné n'existe pas dans le QObject (c'est-à-dire, si elle n'a pas été déclarée avec Q_PROPERTY()), une nouvelle propriété avec le nom et la valeur donné est automatiquement ajoutée au QObject, mais false est toujours retourné. Cela signifie qu'un retour de false ne peut être utilisé pour déterminer si une propriété particulière a actuellement été définie, à moins que vous sachiez à l'avance que la propriété existe déjà dans le QObject. Notez que les propriétés dynamiques sont ajoutées par base d'instance, c'est-à-dire qu'elles sont ajoutée au QObject, non au QMetaObject. Une propriété ne peut être retirée depuis une instance en passant le nom de la propriété et une valeur de QVariant invalide à QObject::setProperty(). Le constructeur par défaut d'un QVariant initialise un QVariant invalide. Les propriétés dynamiques peuvent être récupérées avec QObject::property(), telles que les propriétés sont déclarées au moment de la compilation avec Q_PROPERTY(). Propriétés et types personnalisésLes types personnalisés utilisés par les propriétés nécessitent d'être déclarés par l'utilisation de la macro Q_DECLARE_METATYPE() de sorte que leurs valeurs puissent être enregistrées dans des objets de QVariant. Cela les rend adéquats à l'usage avec les propriétés statiques déclarées avec la macro Q_PROPERTY() dans les définitions de classe, et à l'usage avec les propriétés dynamiques créées lors de l'exécution. Ajouter des informations additionnelles à une classeLa connexion avec le système de propriétés se fait avec une macro additionnelle, Q_CLASSINFO(), qui peut être utilisée pour raccorder la paire nom/valeur à un méta-objet de classe, par exemple : Q_CLASSINFO("Version", "3.0.0") Comme les autres métadonnées, l'information de classe est accessible à l'exécution par le biais du méta-objet ; regardez QMetaObject::classInfo() pour plus de détails. Voir aussi Le système de méta-objets, Les signaux et les slots, Q_DECLARE_METATYPE(), QMetaType et QVariant. RemerciementsMerci à Louis du Verdier pour la traduction ainsi qu'à Thibaut Cuvelier et à Jacques Thery 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.6 | |
Copyright © 2024 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 ? Un bug ? 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 ! |