<h2> Préambule</h2>
<p class="spip">Le but de cet atelier est de montrer les facilités apportées à la programmation d’une interface graphique utilisateur (GUI) par un tool-kit tel que Qt.</p>

<p class="spip">« code less, create more » nous dit Trolltech, la société norvégienne créatrice et distributrice de cet outil (Trolltech : <a href="http://www.trolltech.com/qt" class="spip_out">http://www.trolltech.com/qt</a>).</p>

<h2> Prérequis</h2>
<h3> Connaissances :</h3>
<p class="spip">Pour suivre l’atelier, quelques connaissances de la programmation objet (quelque soit le langage) seraient utiles, mais pas absolument indispensables.</p>

<p class="spip">Ceux qui souhaiteraient en savoir davantage sur le C++ peuvent lire un des nombreux livres existant sur le sujet.</p>

<h3> Installation :</h3>
<p class="spip">Pour exécuter les démonstrations, il faut avoir au préalable installé Qt 4.x.x version Open Source pour Linux. (à partir des sources : temps de compilation relativement long, ou à partir de paquets rpm - voir <a href="http://www.trolltech.com/qt" class="spip_out">http://www.trolltech.com/qt</a>).</p>

<p class="spip">N’oubliez pas d’ajouter les lignes suivantes :</p>

<p class="spip">PATH=/usr/local/Trolltech/Qt-4.2.1/bin :$PATH
	export PATH</p>

<p class="spip">à votre fichier (caché) <i class="spip"> profile </i> (ou <i class="spip"> login </i>, ou <i class="spip"> bash_profile </i> selon votre distrbution) afin de pouvoir exécuter les commandes de compilation des programmes de démonstration.</p>

<h2> Présentation de l’atelier</h2>
<p class="spip">L’atelier comportera plusieurs étapes successives, de la plus simple à la plus compliquée. Chacun pourra compiler, s’il le désire, les programmes correspondants et voir le résultat de leur exécution.</p>

<h2> Première étape : le projet demo1</h2>
<p class="spip">Dans cette première étape on crée une application très simple et on découvre les outils fournis par Qt pour gérer les projets.</p>

<h3> Le listing du fichier main.cpp</h3>
<p class="spip">Le projet <i class="spip"> demo1 </i> de cette première étape comporte un seul fichier <i class="spip"> main.cpp </i> placé dans le répertoire <i class="spip"> demo1 </i> (le nom du projet = le nom du répertoire contenant les fichiers du projet = le nom du fichier exécutable qui sera créé lors de la compilation)</p>

<p class="spip">Listing du fichier <i class="spip"> main.cpp </i> :</p>

<p class="spip">(les numéros de lignes ont été rajoutés pour faciliter les commentaires, mais ils ne font pas partie du listing)</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code><br />
<br />
1 #include <QtGui><br />
<br />
2 <br />
<br />
3 class DemoWindow : public QMainWindow<br />
<br />
4 {<br />
<br />
5 public:<br />
<br />
6    DemoWindow();  //constructeur<br />
<br />
7    QAction *exitAct;<br />
<br />
8    QMenu *fileMenu;<br />
<br />
9 };<br />
<br />
10<br />
<br />
11 DemoWindow::DemoWindow()  //constructeur<br />
<br />
12 {<br />
<br />
13    exitAct = new QAction(tr("E&xit"), this);<br />
<br />
14    exitAct->setShortcut(tr("Ctrl+Q"));<br />
<br />
15    exitAct->setStatusTip(tr("Exit the application"));<br />
<br />
16    connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));<br />
<br />
17<br />
<br />
18    fileMenu = menuBar()->addMenu(tr("&File"));<br />
<br />
19    fileMenu->addAction(exitAct);<br />
<br />
20<br />
<br />
21    statusBar()->showMessage(tr("Ready"));<br />
<br />
22 }<br />
<br />
23<br />
<br />
24<br />
<br />
25 int main(int argc, char *argv[])<br />
<br />
26 {<br />
<br />
27    QApplication app(argc, argv);<br />
<br />
28    DemoWindow mainWin;<br />
<br />
29    mainWin.show();<br />
<br />
30    return app.exec();<br />
<br />
31 }<br />
<br />
</code></div>
<h3> Commentaires : </h3>
<p class="spip">Ligne 1 : on incorpore la bibliothèque QtGui à notre projet.</p>

<p class="spip">Lignes 3 à 9 : déclaration de la classe DemoWindow dérivée de QMainWindow, elle hérite de ce fait de toutes les propriétés de QmainWindow (barre de titre, barre de menus,.barre de statut, barre d’outils etc...). Elle contient uniquement son constructeur, un pointeur sur une instance de la classe QAction et et un pointeur sur une instance de la classe Qmenu. (tous les objets - instances - dont le nom commence par Q sont des objets définis par Qt et qui se trouvent dans les bibliothèques Qt auxquelles on fait appel dans les instructions #include).</p>

<p class="spip">Lignes 11 à 22 : le constructeur de la classe DemoWindow.</p>

<p class="spip">On crée ligne 13 l’objet exitAct (qui pourra être utilisé dans un menu et une barre d’outils), ligne 14 on définit ses touches de raccourcis et ligne 15 le message qui apparaîtra dans la ligne de statut lorsque la ligne de menu correspondante sera sélectionnée ou survolée par la souris.</p>

<p class="spip">Puis, pour que cette Qaction soit utilisable, on utilise ligne 16 le mécanisme SIGNAL/SLOT propre à Qt (Ce mécanisme est décrit en détails dans l’Assistant de Qt) : le signal « triggered » est émis par l’objet exitAct lorsque l’utilisateur clique sur la commande « Exit », ou bien s’il frappe « Ctrl+Q » au clavier. A la réception de ce signal, notre application sait qu’il faut l’associer à une fonction membre très précise qui est le slot « close », et l’exécution de cette fonction provoquera la fermeture de l’application.</p>

<p class="spip">Ligne 18 on ajoute le menu « File » à la barre de menu et ligne 19 on ajoute l’action « exitAct » au menu « File ».</p>

<p class="spip">Enfin, on termine en affichant le message « Ready » dans la barre de statut (ligne 21).</p>

<p class="spip">Lignes 25 à 31 : la fonction main.</p>

<p class="spip">Tout programme C ou C++ doit contenir une fonction main : c’est elle qui est exécutée en premier, et elle doit être placée dans le fichier appelé obligatoirement <i class="spip"> main.cpp </i> pour que le compilateur sache la trouver (c’est la raison pour laquelle le fichier unique de notre projet demo1 s’appelle <i class="spip"> main.cpp  </i>et non pas<i class="spip">  demo1.cpp  </i>par exemple).</p>

<p class="spip">Cette fonction contient les quatre lignes de code suivantes :</p>

<p class="spip">ligne 27 création d’une instance app de QApplication</p>

<p class="spip">ligne 28 création d’une instance mainWin de notre classe DemoWindow</p>

<p class="spip">ligne 29 affichage de mainWin</p>

<p class="spip">ligne 30 exécution de l’instance app, avec retour d’un code indiquant si tout s’est bien passé !</p>

<h3> Fichier de projet et fichier Makefile</h3>
<p class="spip">Qt fournit l’outil « qmake » qui permet de créer facilement le fichier de projet et le fichier Makefile.</p>

<p class="spip">Ouvrir une console et se placer dans le répertoire demo1.</p>

<p class="spip">Exécuter la commande <i class="spip"> qmake -project </i> : le fichier de projet demo1.pro est créé en fonction des fichiers contenus dans le répertoire du projet. Examiner le contenu de ce ficher.</p>

<p class="spip">Exécuter ensuite la commande <i class="spip"> qmake </i> : le fichier Makefile est créé en fonction des éléments contenus dans demo1.pro.</p>

<h3> Compilation :</h3>
<p class="spip">Exécuter la commande <i class="spip"> make </i> : le fichier exécutable demo1 est créé.</p>

<h3> Exécution :</h3>
<p class="spip">Exécuter la commande <i class="spip"> demo1 </i> : l’application qui vient d’être créée est lancée. Il s’agit de l’affichage d’une simple fenêtre avec menus et barre de statut, qui peut être agrandie, réduite, mise en icône, et bien entendu fermée de diverses façons.</p>

<h2> Deuxième étape</h2>
<p class="spip">Pour cette deuxième étape, on va enrichir notre application en la dotant d’un éditeur de textes.</p>

<h3> Le listing du fichier main.cpp modifié</h3>
<p class="spip">Voici ci-après le listing du fichier <i class="spip"> main.cpp </i> modifié (on peut soit modifier le fichier main.cpp du répertoire demo1 soit utiliser le fichier se trouvant dans le répertoire demo2 qui contient les modifications) :</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code><br />
<br />
#include <QtGui><br />
<br />
<br />
<br />
class DemoWindow : public QMainWindow<br />
<br />
{<br />
<br />
public:<br />
<br />
    DemoWindow();  //constructeur<br />
<br />
<br />
<br />
    QAction *exitAct;<br />
<br />
    QMenu *fileMenu;<br />
<br />
<br />
<br />
    QTextEdit *editeur;  //demo 2<br />
<br />
};<br />
<br />
<br />
<br />
DemoWindow::DemoWindow()  //constructeur<br />
<br />
{<br />
<br />
    exitAct = new QAction(tr("E&xit"), this);<br />
<br />
    exitAct->setShortcut(tr("Ctrl+Q"));<br />
<br />
    exitAct->setStatusTip(tr("Exit the application"));<br />
<br />
    connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));<br />
<br />
<br />
<br />
    fileMenu = menuBar()->addMenu(tr("&File"));<br />
<br />
    fileMenu->addAction(exitAct);<br />
<br />
<br />
<br />
    editeur=new QTextEdit;  //demo 2<br />
<br />
    setCentralWidget(editeur);  //demo 2<br />
<br />
<br />
<br />
    resize(400, 300); //demo 2<br />
<br />
<br />
<br />
    statusBar()->showMessage(tr("Ready"));<br />
<br />
}<br />
<br />
<br />
<br />
<br />
<br />
int main(int argc, char *argv[])<br />
<br />
{<br />
<br />
    QApplication app(argc, argv);<br />
<br />
    DemoWindow mainWin;<br />
<br />
    mainWin.show();<br />
<br />
    return app.exec();<br />
<br />
}<br />
<br />
</code></div>
<h3> Commentaires : </h3>
<p class="spip">Dans la déclaration de la classe DemoWindow on déclare la variable editeur qui est un pointeur sur un objet QtextEdit en ajoutant la ligne :</p>

<p class="spip">QTextEdit *editeur ;</p>

<p class="spip">Puis dans le constructeur de DemoWindow on crée l’éditeur en ajoutant la ligne :</p>

<p class="spip">editeur=new QtextEdit ;</p>

<p class="spip">et on lui donne le statut de Widget central :</p>

<p class="spip">setCentralWidget(editeur) ;</p>

<p class="spip">enfin, pour voir un peu mieux ce que l’on fait, on impose les dimensions de la fenêtre (dimensions qu’on pourra modifier comme on veut lors de l’exécution) :</p>

<p class="spip">resize(400, 300) ;</p>

<h3> Exécution :</h3>
<p class="spip">Si vous avez modifié directement le fichier du répertoire demo1, il suffit de l’enregistrer et d’exécuter <i class="spip"> make </i>. (le fichier de projet demo1.pro et le fichier Makefile sont inchangés)</p>

<p class="spip">Si vous avez choisi d’utiliser le répertoire demo2 contenant le fichier déjà modifier, il faut exécuter la séquence complète des commandes :</p>

<p class="spip">qmake -project
qmake
make</p>

<p class="spip">pour créer le fichier de projet demo2.pro et le fichier Makefile correspondant.</p>

<p class="spip">Lancez l’exécution de la nouvelle application : grace à l’ajout de seulement quatre lignes, notre application est devenue un éditeur de textes doté des propriétés classiques des éditeurs de textes (essayez un click droit de la souris pour voir).</p>

<h2> Troisième étape : le projet demo3</h2>
<p class="spip">Les projets demo 1 et 2 ne comportaient qu’un seul fichier, appelé obligatoirement <i class="spip"> main.cpp.  </i>Pour des projets plus importants, il est nécessaire de diviser les listings entre plusieurs fichiers. C’est ce que nous allons faire dans cette 3ème étape, même si la taille du fichier ne le justifie pas.</p>

<h3> Les fichiers du projet, leur listing et les commentaires</h3>
<p class="spip">Le fichier d’en-tête <i class="spip"> demowindow.h </i></p>

<p class="spip">Ce fichier regroupe les déclarations des classes utilisées dans le projet et les prototypes des fonctions (Il ne peut en aucun cas contenir le corps des fonctions).</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code><br />
<br />
#include <QMainWindow><br />
<br />
<br />
<br />
class QAction;<br />
<br />
class QMenu;<br />
<br />
class QTextEdit;<br />
<br />
<br />
<br />
class DemoWindow : public QMainWindow<br />
<br />
{<br />
<br />
public:<br />
<br />
    DemoWindow();  //constructeur<br />
<br />
<br />
<br />
    QAction *exitAct;<br />
<br />
    QMenu *fileMenu;<br />
<br />
<br />
<br />
    QTextEdit *editeur;  //demo 2<br />
<br />
};<br />
<br />
</code></div>
<p class="spip"><strong class="spip">Commentaires : </strong></p>

<p class="spip">La classe DemoWindow étant dérivée de QmainWindow, on doit placer dans notre fichier d’en-tête la première instruction #include <QmainWindow></p>

<p class="spip">Nous déclarons à l’avance les classes Qaction, Qmenu et QtextEdit afin de pouvoir utiliser des références à des objets de ce type dans notre classe DemoWindow.</p>

<p class="spip">La déclaration de la classe DemoWindow est inchangée.</p>

<p class="spip">Le fihier source <i class="spip"> demowindow.cpp </i></p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code><br />
<br />
#include <QtGui><br />
<br />
#include "demowindow.h"<br />
<br />
<br />
<br />
DemoWindow::DemoWindow()  //constructeur<br />
<br />
{<br />
<br />
    exitAct = new QAction(tr("E&xit"), this);<br />
<br />
    exitAct->setShortcut(tr("Ctrl+Q"));<br />
<br />
    exitAct->setStatusTip(tr("Exit the application"));<br />
<br />
    connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));<br />
<br />
<br />
<br />
    fileMenu = menuBar()->addMenu(tr("&File"));<br />
<br />
    fileMenu->addAction(exitAct);<br />
<br />
<br />
<br />
    editeur=new QTextEdit;  //demo 2<br />
<br />
    setCentralWidget(editeur);  //demo 2<br />
<br />
<br />
<br />
    resize(400, 300); //demo 2<br />
<br />
<br />
<br />
    statusBar()->showMessage(tr("Ready"));<br />
<br />
}<br />
<br />
</code></div>
<p class="spip"><strong class="spip">Commentaires : </strong></p>

<p class="spip">Les deux premières lignes :</p>

<p class="spip">#include <QtGui> :</p>

<p class="spip">incorpore la bibliothèque QtGui dans laquelle le compilateur trouvera tout ce qui dépend deQt, y compris les classes que nous avons prédéclarées (QAction etc...)</p>

<p class="spip">#include "demowindow.h" : incorpore les déclarations contenues dans notre ficher d’en-tête.</p>

<p class="spip">Ensuite on trouve le constructeur de DemoWindow, inchangé.</p>

<p class="spip">Le ficher source <i class="spip"> main.cpp </i></p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code><br />
<br />
#include <QApplication><br />
<br />
#include "demowindow.h"<br />
<br />
<br />
<br />
int main(int argc, char *argv[])<br />
<br />
{<br />
<br />
    QApplication app(argc, argv);<br />
<br />
    DemoWindow mainWin;<br />
<br />
    mainWin.show();<br />
<br />
    return app.exec();<br />
<br />
}<br />
<br />
</code></div>
<p class="spip"><strong class="spip">Commentaires : </strong></p>

<p class="spip">Les deux premières lignes :</p>

<p class="spip">#include <QApplication> :  incorpore la déclaration de QApplication
#include "demowindow.h" : incorpore les déclarations contenues dans</p>

<p class="spip">notre ficher d’en-tête.</p>

<p class="spip">Ensuite on retrouve le corps de la fonction main, inchangé.</p>

<h3> Compilation et exécution</h3>
<p class="spip">Ouvrir une console et se placer dans le répertoire demo3.</p>

<p class="spip">Exécuter la commande <i class="spip"> qmake -project </i> : le fichier de projet demo3.pro est créé en fonction des fichiers contenus dans le répertoire du projet. Examiner le conteu de demo3.pro.</p>

<p class="spip">Exécuter ensuite la commande <i class="spip"> qmake </i> : le fichier Makefile est créé en fonction des éléments contenus dans demo3.pro.</p>

<p class="spip">Exécuter la commande <i class="spip"> make </i> : le fichier exécutable demo3 est créé.</p>

<p class="spip">Exécuter la commande <i class="spip"> demo3 </i> : l’application qui vient d’être créée est lancée.</p>

<h2> Suites possibles</h2>
<p class="spip">On peut envisager de réaliser d’autres ateliers pour aller plus loin :
<br /></p>
<li> créer un dialogue avec Qt Designer et voir comment on peut l’utiliser dans notre application ;
<br /><li> utiliser Qt Linguist pour traduire les textes des menus et des messages ;
<br /><li> etc...