FAQ Qt
FAQ QtConsultez toutes les FAQ
Nombre d'auteurs : 26, nombre de questions : 298, dernière mise à jour : 15 juin 2021
La 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