IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo
Sommaire > Généralités
        Est-ce compliqué d'utiliser Qt 4 ?
        Comment compiler des projets utilisant Qt 4 ?
        Peut-on utiliser des pointeurs intelligents sans danger avec des QObject ?
        Comment avoir des classes utilisant Q_OBJECT sans .h ?
        Comment Qt optimise t il les copies ?
        Comment gérer la mémoire avec Qt ?



Est-ce compliqué d'utiliser Qt 4 ?
auteur : Alp Mestan
En réalité, utiliser Qt est plus simple que ce que l'on pense. En effet, le code suivant affiche un bouton qui ferme l'application lorsque l'on clique dessus, et pourtant il ne fait que 13 lignes.

// Nécessaire pour créer une application avec Qt
#include <QApplication> 
// Nécessaire pour pouvoir créer un bouton
#include <QPushButton> 
 
// La fonction main() habituelle
int main(int argc, char **argv) 
{
    // Qt récupère les arguments passés au programme
    QApplication    app(argc, argv); 
    // on crée notre bouton, intitulé "Hello World"
    QPushButton     quit("Hello World!");
    // on le redimensionne
    quit.resize(300, 40);
    // on change la police et la taille
    quit.setFont(QFont("Arial", 18, QFont::Bold)); 
    // on explique à Qt que l'application doit se terminer lors du clic 
    //sur le bouton créé précédemment
    QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));
    // on affiche le bouton 
    quit.show(); 
    // on laisse Qt gérer le code de retour du programme
    return app.exec(); 
}
Comme vous pouvez le voir, il est très simple de gérer ses composants. Pour en découvrir plus, il est bon de consulter la documentation et les exemples de Trolltech, ainsi que les tutoriaux présents sur developpez.


Comment compiler des projets utilisant Qt 4 ?
auteur : Alp Mestan
Les développeurs de Qt 4 proposent des outils très utiles qui facilitent la gestion de vos projets utilisant Qt 4. En effet, il existe un outil permettant de transformer les fichiers du designer (.ui) en fichiers C++, un autre permettant de générer le code nécessaire pour la création de widgets personnalisés, ...

Cependant, ils fournissent également un outil permettant de gérer automatiquement les fichiers du designer, les fichiers dans lesquels vous définissez des widgets personnalisés, et même en réalité tout votre projet : qmake. Cet outil permet de générer un fichier de projet .pro, de générer à partir de ce dernier les règles de compilation de votre projet, et bien d'autres choses comme la détection de votre compilateur, du répertoire d'installation de Qt 4, ...

Un tutoriel a été écrit pour présenter cet outil et décrire son utilisation : fr Compilation des projets Qt 4.

lien : fr Compilation des projets Qt 4

Peut-on utiliser des pointeurs intelligents sans danger avec des QObject ?
auteur : Aurelien.Regat-Barrel
QObject (et toutes les classes qui en dérivent ) ne se marrie pas très bien avec les pointeurs intelligents classiques du C++ tels que auto_ptr ou shared_ptr. Comme expliqué dans la question "Un new sans delete ?", Qt implémente via QObject un mécanisme de gestion de la mémoire dont le principe est qu'un QObject parent détruise automatiquement tous ses objets QObject enfants.

Ce mécanisme est fort pratique et permet de grandement simplifier la gestion de la mémoire. Cependant, il entre en conflit avec tout autre mécanisme de libération de la mémoire tel que ceux implémentés au moyen de pointeurs intelligents.

En effet, si vous déclarez un pointeur intelligent sur une instance de QObject, ce dernier aura en charge la destruction de cette instance. Si par malheur votre QObject se trouve être l'enfant d'un autre QObject, et que ce parent vient à être détruit, votre instance sera elle aussi automatiquement détruite, alors que votre pointeur intelligent continue de pointer vers elle! Et quand votre pointeur intelligent estimera qu'il est temps de la détruire , il effectuera un appel à delete sur un objet déjà détruit (double utilisation de delete) avec toutes les conséquences fâcheuses que l'on connait.

A noter que spécifier un parent nul au moment de la construction de votre QObject ne vous garantie pas pour autant que ce dernier ne sera pas par la suite "reparenté" via la fonction setParent(), chose qui se produit assez régulièrement entre objets graphiques (QWidget).

En conséquences, il est déconseillé d'utiliser des pointeurs intelligents sur des objets de type QObject. Si jamais vous devez néanmoins y avoir recours, vous devez protéger votre instance d'une double deletion au moyen d'un guarded pointer (QPointer en Qt 4, ou QGuardedPtr en Qt 3), comme dans l'exemple suivant :
shared_ptr<QPointer<QWidget> > ptr( new QWidget() );
La particularité d'un guarded pointer est qu'il est automatiquement mis à zéro si l'instance associée est détruite. Ainsi, dans cet exemple, quand shared_ptr effectuera un appel à delete sur une instance déjà détruite, cela reviendra à effectuer un delete sur un pointeur nul, c.a.d à ne rien faire du tout.

Ayez aussi à l'esprit que shared_ptr perd son sens originel et se comporte davantage comme un weak_ptr, c.a.d que vous devez systématiquement vous assurer qu'il ne soit pas nul avant de l'utiliser.

Vu la lourdeur de cette écriture et le changement de sémantique introduit, on comprend mieux pourquoi il est déconseillé d'employer des pointeurs intelligents sur des objets dérivant de QObjet.

lien : fr Faq C++ : pointeurs intelligents
lien : fr Tutoriel : Pointeurs intelligents

Comment avoir des classes utilisant Q_OBJECT sans .h ?
auteur : Yan Verdavaine
En C++, il peut être parfois intéressent de déclarer une classe directement dans un fichier d'implémentation (.cpp,.cxx,.cc ...). Seulement certain class exploité par Qt doivent être moccé.
Pour remédier à ce problème, il est tout à fait possible d'appliquer moc sur ce fichier. En contre partie, il faut inclure le fichier généré à la suite de la déclaration de la classe dans le .cpp.

Si vous utilisez qmake, il suffit, juste après la déclaration de la classe, d'inclure un fichier utilisant le nom du fichier cpp suivi de l'extension .moc. Cette méthode est utilisée dans certain code de la Q/R pour simplifier la compilation de l'exemple à un seul fichier
exemple : fichier nommé test.cpp
...
class myTest : QObject
{
    Q_OBJECT
    ...
};
#include "test.moc"
...

Comment Qt optimise t il les copies ?
auteur : Yan Verdavaine
Qt est basé sur une sémantique de copie. C'est à dire qu'elle utilise beaucoup la copie pour permettre de créer des logiciels robuste et évite un bon nombre de bugs. Pour optimiser cela, Qt implémente le pattern COW (Copy on Write). I.e. la copie interne est réellement effectuée lors d'un accès en écriture sur un objet interne partagé d'une classe. Dit d'une autre manière, Qt va partager en lecture un objet interne entre différent instances égaux d'une classe.

Le principe est le suivant :
  1. Lors d'une copie, un objet interne est partagé.
  2. Tant qu'aucune des instances ne modifient cette objet, il reste partagé.
  3. Dès qu'une des instances modifie l'objet , cette instance va copier l'objet interne et appliquer la modification.
//s1 va créer un objet interne contenant "hello word"
QString s1 = "hello word";
 
//s2 va référencer le même objet interne que s1. 
//Il n'y as pas eu de vrai copie.
QString s2 = s1;
 
//accès en lecture au premier caractère => inutile de faire une copie
qDebug()<< s2[0];
 
// on veut modifier la première lettre de s2
// s2 créé un nouvel objet interne et  copie le contenue.
// s1 et s2 n'utilisent plus le même objet interne
// s2 modifie la première lettre
s2[0] = 'b';
Remarque : ce pattern est thread safe dans l'implémentation Qt

lien : en Liste des classes Qt basées sur le COW

Comment gérer la mémoire avec Qt ?
auteur : Benjamin Poulain
Qt est conçu de façon à rendre aisée la gestion de la mémoire. Il y a deux mécanismes pour y arriver: les types simples et les hiérarchies.

Les objets simples, tel que les chaînes de caractères, container, etc... peuvent être manipulés comme les types de bases, la mémoire est nettoyée automatiquement par le destructeur
Par exemple:
QString getSiteName()
{
    // pas de problème à l'allouer sur la pile
    QString siteName = "Developpez.com"; 
    // pas de problème à l'utiliser comme type de retour
    return siteName; 
}
Ce type d'objet n'utilise en interne qu'un pointeur vers un délégué, ce qui veut dire que ces objets sont extrêmement rapides à manipuler:
QRectF rect(0.0, 0.0, 50.0, 50.0);
// le constructeur par copie est rapide
QRectF rectClone = rect; 
QRectF copy;
// l'affectation est tout aussi rapide
copy = rect; 
Ce type d'objet est donc très facile à utiliser car on peut l'employer comme si il s'agissait d'un type de base.

D'autres objets ont besoins d'une gestion de mémoire plus complexe car il faut contrôler précisément leur durée de vie. Pour ces objets, Qt a introduit le mécanisme de hiérarchie d'objet, qui est disponible pour toutes les sous-classes de QObject.

Les objets d'une hiérarchie peuvent avoir un objet parent, et des objets enfants (à ne pas confondre avec l'héritage, il s'agit ici d'encapsulation). Lorsqu'un objet est détruit, tous ses objets enfants sont détruits aussi.

Le parent est précisé dans le constructeur des objets ou grâce à la méthode QObjet::setParent(). Voici un exemple:
QString giveString()
{
    QObjet parent;
    MyObjet *myObjet = new MyObject(parent);
    myObjet->doSomeComputation();
    return myObjet->getString();
}
Étonnamment, le code précédent n'a pas de fuite de mémoire. L'objet MyObjet, créé sur le tas, a comme parent le QObject "parent". Lorsque parent arrive à la fin de la fonction giveString(), son destructeur se charge de supprimer l'objet myObjet.

L'exemple précédent est artificiel, voyons un exemple plus réaliste:
void showMessage()
{
    QDialog dialog;
    QVBoxLayout *layout = new QVBoxLayout(&dialog);
    QLabel *message = new QLabel("Cliquez sur le bouton");
    layout->addWidget(message);
    QButton *button = new QButton("Cliquez ici");
    layout->addWidget(button);
    dialog.exec();
}
Quelle magie fait que ce code fonctionne? Lorsqu'un widget est ajouté au layout, le layout le reparente automatiquement avec son widget propriétaire (dialog dans ce cas ci). Finalement, lorsque la fonction se termine, le destructeur de "dialog" supprime tous les objets et nettoie la mémoire.

lien : faq Comment optimiser la copie de ses classes ?
lien : faq Comment optimiser la copie de ses classes ?


Consultez les autres F.A.Q's


Valid XHTML 1.1!Valid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.