FAQ Qt

FAQ QtConsultez toutes les FAQ
Nombre d'auteurs : 26, nombre de questions : 298, dernière mise à jour : 15 juin 2021
Sommaire→Généralités techniques→MétaobjetsLa classe QObject (et donc toutes les classes dérivées) possède la variable
protected :
static const QMetaObject staticQtMetaObject;Cette instance donne accès aux métadonnées de l'espace de noms de Qt. Les métadonnées accessible sont exclusivement des énumerateurs.
Voici un exemple qui affiche sous forme d'arbre tous les énumérateurs de l'espace de noms de Qt et leurs valeurs.
#include <QtGui>
class monWidget : public QWidget
{
QAbstractItemModel * createModel()
{
QStandardItemModel * model = new QStandardItemModel(this);
// parcours de toutes les enum du namespace Qt
for (int i = 0; i < staticQtMetaObject.enumeratorCount(); ++i)
{
// ième enumerateur
QMetaEnum iEnum = staticQtMetaObject.enumerator(i);
QStandardItem * parent = new QStandardItem(iEnum.name());
// parcours de toutes les valeurs de l'enum
for (int j = 0; j < iEnum.keyCount(); ++j)
{
QList<QStandardItem *> items;
// jième valeur de l'enum
int value = iEnum.value(j);
// chaîne correspondant à la valeur dans l'enum
items << new QStandardItem(iEnum.valueToKey(value));
// valeur sous forme hexadécimale
items << new QStandardItem("0x0" + QString::number(value,16).toUpper());
parent->appendRow(items);
}
model->appendRow(parent);
}
model->setColumnCount(2);
model->setHeaderData(0, Qt::Horizontal, "Enumerateur", Qt::DisplayRole);
model->setHeaderData(1, Qt::Horizontal, "Valeur", Qt::DisplayRole);
return model;
}
public :
monWidget()
{
resize(400,600);
QVBoxLayout * layout = new QVBoxLayout(this);
QTreeView * treeView = new QTreeView;
treeView->setModel(createModel());
treeView->header()->setResizeMode(QHeaderView::ResizeToContents);
layout->addWidget(treeView);
}
};
int main(int argc, char * argv[])
{
QApplication app(argc,argv);
monWidget widget;
widget.show();
return app.exec();
}Comme staticQtMetaObject n'est pas documenté, cela est susceptible d'être modifié dans une version future de Qt.
Le moc n'extrait et ne stocke pas les informations de toutes les méthodes mais uniquement celles qui sont indiquées comme nécessitant ces opérations. Par exemple, les informations d'un constructeur déclaré dans la section publique sans instruction particulière au moc ne seront pas extraites, tandis que les méthodes déclarées dans la partie des signaux le seront. Pour que le moc recense une méthode, il faut soit la définir en tant que signal ou slot, soit utiliser une instruction particulière.
Voici les principales instructions utilisables pour signaler au moc que le recensement doit être effectué, ainsi que leur effet :
- Q_INVOKABLE : permet au métaobjet d'appeler la méthode ;
- Q_SIGNAL : marque la méthode en tant que signal ;
- Q_SLOT : marque la méthode en tant que slot.
Il est possible de déduire des informations de la documentation de Q_INVOKABLE que cette macro est uniquement conçue pour les méthodes. Il faut toutefois noter que seuls les constructeurs ayant été déclarés avec le modificateur Q_INVOKABLE sont rendus disponibles à travers le système de méta-objets. L'utilisation de Q_INVOKABLE n'est donc pas limitée aux méthodes.
Par exemple :
class MyWidget : public QWidget
{
Q_OBJECT
public:
Q_INVOKABLE MyWidget(QObject *parent = 0); // Constructeur recensé
void myFunction(); // Méthode non recensée
Q_INVOKABLE void myOtherFunction(); // Méthode recensée
Q_SLOT void mySlot(); // Slot recensé
public slots:
void myOtherSlot(); // Slot recensé
};Lien : Qu'est-ce que le moc ?
La principale raison de la présence du système de métaobjets est le besoin d'instaurer un mode de communication entre les objets, qu'ils aient ou non un lien entre eux. Autrement dit, le système de signaux et de slots est la principale cause de la présence du système de méta-objets dans le framework Qt. Cette raison fait d'ailleurs l'objet de critiques de la part de gens pensant que l'utilisation des templates serait plus appropriée pour gérer cela. La documentation répond d'ailleurs à ces critiques.
Le système de métaobjets est nécessaire aux dispositifs suivants :
- le système de signaux et de slots, qui permet la communication entre des objets sans rapport particulier ;
- l'introspection, soit la capacité d'un programme à analyser son état lors de l'exécution ;
- le système de propriétés, un dispositif multiplateforme de gestion de valeurs avec au minimum une fonction de lecture.
Exemples de frameworks/autres s'appuyant en grande partie sur le système de métaobjets :
- QtScript, qui permet de manipuler une instance de QObject par du JavaScript ;
- QtAnimation, qui permet de modifier une propriété au fil du temps ;
- QtStateMachine, qui permet de modifier une propriété ;
- QML, qui permet de manipuler une instance de QObject.
Lien : Pourquoi Qt n'utilise pas les templates pour les signaux et les slots ?
Le moc (meta-object compiler, compilateur de métaobjets en français) est utilisé dans une étape additionnelle de la compilation. Make se sert du moc lorsqu'il est appelé, mais celui-ci peut aussi être appelé manuellement. Tout dépend donc des besoins.
Le fonctionnement du moc est simple : il lit les fichiers source et retrouve les déclarations de classe où la macro Q_OBJECT est utilisée. Une fois cela terminé, il génère des fichiers, reconnaissables par leur nom sous la forme de moc_[Nom du fichier d'en-tête].cpp (dans le cas d'une utilisation de Q_OBJECT dans un fichier d'en-tête) ou bien sous la forme de [Nom du fichier].moc (dans le cas d'une utilisation de la macro sans fichier d'en-tête), qui contiendront le code de méta-objet par exemple nécessaire à l'utilisation des signaux et des slots.
Ce système possède tout de même des points faibles. Par exemple, il ne gère pas correctement les classes templates qui se voient donc être privées des signaux et des slots. La documentation détaille les limitations que cause le moc.
Q_OBJECT est une macro qui permet à la classe la contenant dans sa section privée de posséder un métaobjet, à condition qu'elle hérite, directement ou non, de QObject. Si la classe n'hérite pas de QObject, utilisez Q_GADGET à la place de Q_OBJECT.
class MyWidget : public QWidget
{
Q_OBJECT
// ...
};De nombreuses méthodes nécessitent la présence de la macro Q_OBJECT pour fonctionner correctement, et c'est pour cela qu'il est recommandé à plusieurs reprises par la documentation de l'utiliser « dans toutes les sous-classes de QObject sans prêter attention au fait qu'elles utilisent actuellement ou non les signaux, les slots et les propriétés ».
Lien : De QObject aux métaobjets, une plongée au cœur des fondations de Qt






