Aller au menu - Aller au contenu

Modéliser ses fenêtres avec Qt Designer


Informations sur le tutoriel

Avatar
Auteur : M@teo21
Visualisations : 1 448 816
Licence : Creative Commons BY-NC-SA


Plus d'informations Plus d'informations

Historique des mises à jour

  • Le 08/03/2010 à 20:26:50
    Correction orthographique, ticket n°1777
  • Le 27/02/2010 à 17:15:14
    Ticket #1729
  • Le 25/02/2010 à 19:58:20
    Correction orthographique.
A force d'écrire le code de vos fenêtres, vous devez peut-être commencer à trouver ça long et répétitif. C'est amusant au début, mais au bout d'un moment on en a un peu marre d'écrire des constructeurs de 3 kilomètres de long juste pour placer les widgets sur la fenêtre.

C'est là que Qt Designer vient vous sauver la vie. Il s'agit d'un programme livré avec Qt (vous l'avez donc déjà installé) qui permet de dessiner vos fenêtres visuellement. Mais plus encore, Qt Designer vous permet aussi de modifier les propriétés des widgets, d'utiliser des layouts, et d'effectuer la connexion entre signaux et slots.

Qt Designer n'est pas un programme magique qui va réfléchir à votre place. Il vous permet juste de gagner du temps et d'éviter les tâches répétitives d'écriture du code de génération de la fenêtre.
N'utilisez PAS Qt Designer et ne lisez PAS ce chapitre si vous ne savez pas coder vos fenêtres à la main. En clair, si vous avez voulu sauter les chapitres précédents et juste lire celui-ci parce que vous le trouvez attirant, vous allez vous planter. C'est dit. :-°


Nous commencerons par apprendre à manipuler Qt Designer lui-même. Vous verrez que c'est un outil complexe mais qu'on s'y fait vite car il est assez intuitif.
Ensuite, nous apprendrons à utiliser les fenêtres générées avec Qt Designer dans notre code source. Comme vous le verrez, il y a plusieurs façons de faire en fonction de vos besoins.

C'est parti ! :)
Chapitre précédent Sommaire Chapitre suivant

Présentation de Qt Designer

Qt Designer Icône

Nous allons commencer par démarrer directement Qt Designer.
Normalement, un raccourci a déjà été créé sur votre système (cf icône ci-contre).


Attention : si vous utilisez un thème personnalisé sur votre ordinateur (par exemple un thème Windows XP téléchargé sur internet), il se pourrait que Qt Designer rencontre des bugs d'affichage. Essayez de désactiver le thème personnalisé et de revenir au thème par défaut avant d'exécuter Qt Designer.



Choix du type de fenêtre à créer



Lorsque vous lancez Qt Designer, il vous propose de créer un nouveau projet. Vous avez le choix entre plusieurs types de fenêtres :

Introduction de Qt Designer


Les 3 premiers choix correspondent à des QDialog.
Vous pouvez aussi créer une QMainWindow si vous avez besoin de gérer des menus et des barres d'outils.
Enfin, le dernier choix correspond à une simple fenêtre de type QWidget.

Pour nos exemples, nous allons choisir de créer une fenêtre simple de type QWidget. Sélectionnez donc le choix Widget.

Il y a d'autres choix que je ne détaillerai pas ici, dans les sous-catégories "Widgets" et "Custom Widgets". Par exemple, on peut créer une fenêtre-QGroupBox.
Vous utiliserez très rarement ces choix.



Analyse de la fenêtre de Qt Designer



Lorsque vous avez créé un nouveau projet, la fenêtre de Qt Designer commence à s'animer et... comme vous pouvez le voir, c'est assez complet :

Fenêtre de Qt Designer


Wow ! Mais comment je vais faire pour m'y retrouver avec tous ces boutons ? :o


En y allant méthodiquement. :)
Détaillons chacune des zones importantes dans l'ordre :

  1. Sur la barre d'outils de Qt Designer, au moins 4 boutons méritent votre attention. Ce sont les 4 boutons situés sous la marque "(1)" rouge que j'ai placée sur la capture d'écran.

    Barre outils layouts


    Ils permettent de passer d'un mode d'édition à un autre. Qt Designer propose 4 modes d'édition :

    • Edit Widgets : le mode par défaut, que vous utiliserez le plus souvent. Il permet d'insérer des widgets sur la fenêtre et de modifier leurs propriétés.
    • Edit Signals/Slots : permet de créer des connexions entre les signaux et les slots de vos widgets.
    • Edit Buddies : permet d'associer des QLabel avec leurs champs respectifs. Lorsque vous faites un layout de type QFormLayout, ces associations sont automatiquement créées.
    • Edit Tab Order : permet de modifier l'ordre de tabulation entre les champs de la fenêtre, pour ceux qui naviguent au clavier et passent d'un champ à l'autre en appuyant sur la touche "Tab".

    Nous ne verrons dans ce chapitre que les 2 premiers modes (Edit Widgets et Edit Signals/Slots). Les autres modes sont peu importants et je vous laisse les découvrir par vous-mêmes.

  2. Au centre de Qt Designer, vous avez la fenêtre que vous êtes en train de dessiner. Pour le moment celle-ci est vide.
    Si vous créez une QMainWindow, vous aurez en plus une barre de menus et une barre d'outils. Leur édition se fait à la souris, c'est très intuitif.
    Si vous créez une QDialog, vous aurez probablement des boutons "OK" et "Annuler" déjà disposés.

  3. Widget Box : ce dock vous donne la possibilité de sélectionner un widget à placer sur la fenêtre. Vous pouvez constater qu'il y a un assez large choix ! Heureusement, ceux-ci sont organisés par groupes pour y voir plus clair.
    Pour placer un de ces widgets sur la fenêtre, il suffit de faire un glisser-déplacer. Simple et intuitif.

    Les widgets en bas de la liste sont soit d'anciens widgets, soit des widgets modifiés non standards. Vous ne devriez pas avoir besoin d'y toucher.


  4. Property Editor : lorsqu'un widget est sélectionné sur la fenêtre principale, vous pouvez éditer ses propriétés. Vous noterez que les widgets possèdent en général beaucoup de propriétés, et que celles-ci sont organisées en fonction de la classe dans laquelle elles ont été définies. On peut ainsi modifier toutes les propriétés dont un widget hérite, en plus des propriétés qui lui sont propres.

    Comme toutes les classes héritent de QObject, vous aurez toujours la propriété objectName. C'est le nom de l'objet qui sera créé. N'hésitez pas à le personnaliser, afin d'y voir plus clair tout à l'heure dans votre code source (sinon vous aurez par exemple des boutons appelés pushButton, pushButton_2, pushButton_3, ce qui n'est pas très clair).

    Si aucun widget n'est sélectionné, ce sont les propriétés de la fenêtre que vous éditerez. Vous pourrez donc par exemple modifier son titre avec la propriété windowTitle, son icône avec windowIcon, etc.

  5. Object Inspector : affiche la liste des widgets placés sur la fenêtre, en fonction de leur relation de parenté, sous forme d'arbre. Ca peut être pratique si vous avez une fenêtre complexe et que vous commencez à vous perdre dedans. Vous pouvez ainsi y voir par exemple que votre fenêtre contient un QGroupBox qui contient 3 cases à cocher.

  6. Signal / slot editor : si vous avez associé des signaux et des slots, les connexions du widget sélectionné apparaissent ici. Nous verrons comment réaliser des connexions dans Qt Designer tout à l'heure.

  7. Resource Browser : un petit utilitaire qui vous permet de naviguer à travers les fichiers de ressources de votre application. Ces fichiers de ressources rappellent un peu ceux de Windows (on en a brièvement parlé dans l'annexe du cours de C, à propos de l'ajout d'icône à un programme sous Windows).
    Ici, les fichiers de ressouces portent l'extension .qrc et ont l'avantage d'être compatibles avec tous les OS.

    Les fichiers de ressources servent empaqueter des fichiers (images, sons, texte...) au sein même de votre exécutable. Cela permet d'éviter d'avoir à placer ces fichiers dans le même dossier que votre programme, et cela évite donc le risque de les perdre (puisqu'ils se trouveront toujours dans votre exécutable).


    C'est un peu hors-sujet, donc je n'en parlerai pas plus ici. Consultez la doc à propos des ressources si vous voulez en savoir plus.

  8. Action Editor : permet de créer des QAction. C'est donc utile lorsque vous créez une QMainWindow avec des menus et une barre d'outils.

Voilà qui devrait suffire pour une présentation générale de Qt Designer. Maintenant, pratiquons un peu. :)

Placer des widgets sur la fenêtre

Placer des widgets sur la fenêtre est en fait très simple : vous prenez le widget que vous voulez dans la liste à gauche, et vous le faites glisser où vous voulez sur la fenêtre.

Ce qui est très important à savoir, c'est qu'on peut placer ses widgets de 2 manières différentes :

  • De manière absolue : vos widgets seront disposés au pixel près sur la fenêtre. C'est la méthode par défaut, la plus précise, mais la moins flexible aussi. Je vous avais parlé de ses défauts dans le chapitre sur les layouts.
  • Avec des layouts (recommandé pour les fenêtres complexes) : vous pouvez utiliser tous les layouts que vous connaissez. Verticaux, horizontaux, en grille, en formulaire... Grâce à cette technique, les widgets s'adapteront automatiquement à la taille de votre fenêtre.


Commençons par les placer de manière absolue, puis nous verrons comment utiliser les layouts dans Qt Designer.

Placer les widgets de manière absolue



Je vous propose pour vous entraîner de faire une petite fenêtre simple composée de 3 widgets :

  • QSlider
  • QLabel
  • QProgressBar

Votre fenêtre devrait à peu près ressembler à ceci maintenant :

Formulaire Designer


Vous pouvez déplacer ces widgets comme bon vous semble sur la fenêtre.
Vous pouvez les agrandir ou les rétrécir.

Quelques raccourcis à connaître :

  • En maintenant la touche Shift appuyée, vous pouvez sélectionner plusieurs widgets en même temps.
  • Faites Suppr pour supprimer les widgets sélectionnés.
  • Si vous maintenez la touche Ctrl enfoncée lorsque vous déplacez un widget, celui-ci sera copié.
  • Vous pouvez double-cliquer sur un widget pour modifier son nom (il vaut mieux donner un nom personnalisé plutôt que laisser le nom par défaut).
    Sur certains widgets complexes, comme la QComboBox (liste déroulante), le double clic a pour effet de vous permettre d'éditer la liste des éléments contenus dans la liste déroulante.
  • Pensez aussi à faire un clic droit sur les widgets pour modifier certaines propriétés, comme la bulle d'aide (toolTip).


Vous pouvez prévisualiser la fenêtre en faisant Ctrl + R, ou encore en allant dans le menu "Form / Preview".

Le menu "Form / Preview in..." vous permet de prévisualiser la fenêtre dans un autre style (Windows, Windows XP, Windows Vista, Plastique, CDE...)


Voici notre fenêtre en mode "Preview" :

Prévisualisation de la fenêtre



Ce mode nous permet de tester la fenêtre telle qu'elle apparaîtra à la fin, de manipuler les widgets, etc.
Sortez du mode Preview et revenez à l'édition, nous avons encore des choses à voir.

Utiliser les layouts



Pour le moment, nous n'utilisons aucun layout. Si vous essayez de redimensionner la fenêtre, vous verrez que les widgets ne s'adaptent pas à la nouvelle taille et qu'ils peuvent même disparaître si on réduit trop la taille de la fenêtre !

Il y a 2 façons d'utiliser des layouts :

  • Utiliser la barre d'outils en haut.
  • Glisser-déplacer des layouts depuis le dock de sélection de widgets ("Widget Box").


Pour une fenêtre simple comme celle-là, nous n'aurons besoin que d'un layout principal.
Pour définir ce layout principal, le mieux est de passer par la barre d'outils :

Barre outils layouts


Cliquez sur une zone vide de la fenêtre (en clair, il faut que ce soit la fenêtre qui soit sélectionnée et non un de ses widgets). Vous devriez alors voir les boutons de la barre d'outils des layouts s'activer, comme sur l'image ci-dessus.

Cliquez sur le bouton correspondant au layout vertical (le second) pour organiser automatiquement la fenêtre selon un layout vertical. :)
Vous devriez alors voir vos widgets s'organiser comme ceci :

Layout vertical


C'est le layout vertical qui les place comme ça afin qu'ils occupent toute la taille de la fenêtre. Bien sûr, vous pouvez réduire la taille de la fenêtre si vous le désirez.
Vous pouvez aussi demander à ce que la fenêtre soit réduite à la taille minimale acceptable, en cliquant sur le bouton tout à droite de la barre d'outils, intitulé "Adjust Size".

Maintenant que vous avez défini le layout principal de la fenêtre, sachez que vous pouvez insérer un sous-layout en plaçant par exemple un des layouts proposés dans la Widget Box.



Insérer des spacers



Vous trouvez que la fenêtre est un peu moche si on l'agrandit trop ?
Moi aussi. Les widgets sont trop espacés, ça ne me convient pas.

Pour changer la position des widgets tout en conservant le layout, on peut insérer un spacer. Il s'agit d'un widget invisible qui sert à créer de l'espace sur la fenêtre.

Le mieux est encore d'essayer pour comprendre ce que ça fait. Dans la Widget Box, vous devriez avoir une section "Spacers" :


Spacers


Prenez un "Vertical Spacer", et insérez-le tout en bas de la fenêtre. Vous devriez alors voir ceci :

Fenêtre avec spacer


Le spacer va forcer les autres widgets à se coller tout en haut. Ils sont toujours organisés selon un layout, mais au moins maintenant nos widgets sont plus rapprochés les uns des autres.
Essayez de déplacer le spacer sur la fenêtre pour voir. Placez-le entre le libellé et la barre de progression. Vous devriez voir que la barre de progression se colle maintenant tout en bas.

Le comportement du spacer est assez logique, mais il faut l'essayer pour bien comprendre. ;)


Editer les propriétés des widgets



Il nous reste une chose très importante à voir : l'édition des propriétés des widgets.
Sélectionnez par exemple le libellé (QLabel). Regardez le dock intitulé "Property Editor". Il affiche maintenant les propriétés du QLabel :

Editeur de propriétés


Ces propriétés sont organisées en fonction de la classe dans laquelle elles ont été définies, et c'est une bonne chose. Je m'explique.
Vous savez peut-être qu'un QLabel hérite de QFrame, qui hérite de QWidget, qui hérite lui-même de QObject ?

Chacune de ces classes définit des propriétés. QLabel hérite donc des propriétés de QFrame, QWidget et QObject, mais a aussi des propriétés qui lui sont propres.

Sur ma capture d'écran ci-dessus, on peut voir une propriété de QObject : objectName. C'est le nom de l'objet qui sera créé dans le code. Je vous conseille de le personnaliser pour que vous puissiez vous y retrouver dans le code source ensuite.

La plupart du temps, on peut éditer le nom d'un widget en double-cliquant dessus sur la fenêtre.


Si vous descendez un peu plus bas dans la liste, vous devriez vous rendre compte qu'un grand nombre de propriétés sont proposées par QWidget (notamment la police, le style de curseur de la souris, etc.).Descendez encore plus bas. Vous devriez arriver sur les propriétés héritées de QFrame, puis celles propres à QLabel :

Editeur de propriétés


Comme vous pouvez le voir, ces propriétés ont été mises en valeur : elles sont en vert.
Je trouve que c'est très bien d'avoir organisé les propriétés comme ça. Ainsi, on voit bien où elles sont définies.

Vous devriez modifier la propriété text, pour changer le texte affiché dans le QLabel. Mettez par exemple "0". Amusez-vous à changer la police (propriété font issue de QWidget) ou encore à mettre une bordure (propriété frameShape issue de QFrame).

Vous remarquerez que lorsque vous éditez une propriété, son nom s'affiche en gras pour être mis en valeur. Cela vous permet par la suite de repérer du premier coup d'oeil les propriétés que vous avez modifiées.

Certaines propriétés, comme alignement de QLabel, possèdent des sous-propriétés. Cliquez sur la petite flèche à gauche pour afficher et modifier ces sous-propriétés. Essayez de faire en sorte que le texte de notre libellé soit centré horizontalement par exemple.


Modifiez aussi les propriétés de la QProgressBar pour qu'elle affiche 0% pour défaut (propriété value).

Vous pouvez aussi modifier les propriétés de la fenêtre. Cliquez sur une zone vide de la fenêtre afin qu'aucun widget ne soit sélectionné. Le dock "Property Editor" vous affichera alors les propriétés de la fenêtre (ici, notre fenêtre est un QWidget, donc vous aurez juste les propriétés de QWidget).

Astuce : si vous ne comprenez pas à quoi sert une propriété, cliquez dessus puis appuyez sur la touche F1. Qt Designer lancera automatiquement Qt Assistant pour afficher l'aide sur la propriété sélectionnée.


Essayez d'avoir une fenêtre qui ressemble au final grosso modo à la mienne :

Fenêtre avec propriétés éditées


Le libellé et la barre de progression doivent afficher 0 par défaut.


Bravo, vous savez maintenant insérer des widgets, les organiser selon un layout et personnaliser leurs propriétés dans Qt Designer ! :)
Nous n'avons utilisé pour le moment que le mode "Edit Widgets". Il nous reste à étudier le mode "Edit Signals/Slots"...

Configurer les signaux et les slots

Passez en mode "Edit Signals/Slots" en cliquant sur le second bouton de la barre d'outils :

Barre outils layouts


Vous pouvez aussi appuyer sur la touche F4. Vous pourrez faire F3 pour revenir au mode d'édition des widgets.


Dans ce mode, on ne peut pas ajouter, modifier, supprimer, ni déplacer de widgets. Par contre, si vous pointez sur les widgets de votre fenêtre, vous devriez voir un cadre rouge autour d'eux.

Vous pouvez, de manière très intuitive, associer les widgets entre eux pour créer des connexions simples entre leurs signaux et slots. Je vous propose par exemple d'associer le QSlider avec notre QProgressBar.

Pour cela, cliquez sur le QSlider et maintenez le bouton gauche de la souris enfoncé. Pointez sur la QProgressBar et relâchez le bouton. La connexion que vous allez faire devrait ressembler à ceci :

Connexion dans Qt Designer


Une fenêtre apparaît alors pour que vous puissiez choisir le signal et le slot à connecter :

Choix des signaux et slots


A gauche : les signaux disponibles dans le QSlider.
A droite : les slots compatibles disponibles dans la QProgressBar.

Sélectionnez un signal à gauche, par exemple sliderMoved(int). Ce signal est envoyé dès que l'on déplace un peu le slider.
Vous verrez que la liste des slots compatibles apparaît à droite.

En fonction du signal choisi, Qt Designer ne vous affiche que les slots de destination compatibles. Par exemple, sliderMoved(int) s'accorde bien avec setValue(int). On peut aussi le connecter à reset(), dans ce cas le nombre envoyé en paramètre sera perdu.
Par contre, on ne peut pas connecter le signal sliderMoved(int) au slot setRange(int, int) car le signal n'envoie pas assez de paramètres. D'ailleurs, vous ne devriez pas voir ce slot disponible dans la liste des slots si vous avez choisi le signal sliderMoved(int), ce qui vous empêche de créer une connexion incompatible.


Nous allons connecter sliderMoved(int) du QSlider avec setValue(int) de la QProgressBar.
Faites OK pour valider une fois le signal et le slot choisis. C'est bon, la connexion est créée. :)

Connexion effectuée


Faites de même pour associer sliderMoved(int) du QSlider à setNum(int) du QLabel.


Notez que vous pouvez aussi connecter un widget à la fenêtre. Dans ce cas, visez une zone vide de la fenêtre. La flèche devrait se transformer en symbole de masse (bien connu par ceux qui font de l'électricité ou de l'électronique) :

Connexion à la masse


Cela vous permet d'associer un signal du widget à un slot de la fenêtre, ce qui peut vous être utile si vous voulez créer un bouton "Fermer la fenêtre" par exemple.

Attention : si dans la fenêtre du choix du signal et du slot vous ne voyez aucun slot s'afficher pour la fenêtre, c'est normal. Qt les masque par défaut car ils sont nombreux. Si on les affichait pour chaque connexion entre 2 widgets, on en aurait beaucoup trop (puisque tous les widgets héritent de QWidget).
Pour afficher quand même les signaux et slots issus de QWidget, cochez la case "Show signals and slots inherited from QWidget".


Passez maintenant en mode preview (Ctrl + R) pour tester vos connexions.
Essayez de déplacer le slider. Si vous avez fait les choses correctement, vous devriez voir le libellé et la barre de progression changer de valeur en même temps ! :D

Prévisualisation de la fenêtre


Pour des connexions simples entre les signaux et les slots des widgets, Qt Designer est donc très intuitif et convient parfaitement.

Eh, mais si je veux créer un slot personnalisé pour faire des manipulations un peu plus complexes, comment je fais ?


Qt Designer ne peut pas vous aider pour ça. Si vous voulez créer un signal ou un slot personnalisé, il faudra le faire tout à l'heure dans le code source.
Comme vous pourrez le voir néanmoins, c'est très simple à faire.

En y réfléchissant bien, c'est même d'ailleurs la seule chose que vous aurez à coder ! En effet, tout le reste est automatiquement géré par Qt Designer. Vous n'avez plus qu'à vous concentrer sur la partie "réflexion" de votre code source.
Qt Designer vous permet donc de gagner du temps en vous épargnant les tâches répétitives et basiques qu'on fait à chaque fois que l'on crée une fenêtre.

Utiliser la fenêtre dans votre application

Il reste une dernière étape, et pas des moindres : apprendre à utiliser la fenêtre ainsi créée dans votre application.


Notre nouvel exemple



Je vous propose de créer une nouvelle fenêtre (parce que l'exemple de tout à l'heure était bien joli, mais pas très intéressant à part pour tester les signaux et slots :-° ). On va créer une mini-calculatrice :

Mini calculatrice


Essayez de reproduire à peu près la même fenêtre que moi.
Un layout principal horizontal suffira à organiser les widgets.

La fenêtre est constituée des widgets suivants, de gauche à droite :

WidgetNom de l'objet
QSpinBox nombre1
QComboBox operation
QSpinBox nombre2
QPushButton boutonEgal
QLabel resultat


Pensez à bien renommer les widgets afin que vous puissiez vous y retrouver dans votre code source ensuite. ;)
Pensez aussi à donner un nom à la fenêtre. Je l'ai appelée "FenCalculatrice".

Pour la liste déroulante du choix de l'opération, je l'ai déjà pré-remplie avec 4 valeurs : +, -, * et /.
Double-cliquez sur la liste déroulante pour ajouter / supprimer des valeurs.


Enregistrez cette fenêtre dans le dossier de votre projet. Je lui ai donné le nom calculatrice.ui.
Tous les fichiers de fenêtres créés avec Qt Designer portent l'extension .ui (comme User Interface, "Interface Utilisateur" en français).


Le principe de la génération du code source



Essayons maintenant de récupérer le code de la fenêtre dans notre application et d'ouvrir cette fenêtre.

Le code ? Quel code ? Je ne vois pas de code moi ?
Qt Designer est censé générer un code source ?


Non, Qt Designer ne fait que produire un fichier .ui. C'est le petit programme uic qui se charge de transformer le .ui en code source C++.

Voilà ce que ça donne schématiquement :

Schéma compilation des UI


Vous dessinez la fenêtre avec Qt Designer qui produit un fichier .ui.
Ce fichier est transformé automatiquement en code source par le petit programme en ligne de commande uic. Celui-ci génèrera un fichier ui_nomDeVotreFenetre.h. Qt met tout le code dans le fichier .h, ne vous étonnez donc pas s'il n'y a pas de .cpp correspondant.

Vous continuez à programmer vos autres fichiers source comme avant (.cpp et .h).
A la compilation, le fichier ui_nomDeVotreFenetre.h sera compilé avec vos autres fichiers source !

Pour information : ce n'est pas obligatoire, mais si vous voulez voir le code source qui sera généré pour votre fenêtre, vous pouvez à tout moment aller dans le menu "Form / Preview Code..." de Qt Designer.
Regardez ce code mais ne l'enregistrez pas. C'est vraiment juste pour avoir une idée de ce à quoi ressemblera le code généré.


Nous allons procéder en 2 étapes :

  1. Nous allons mettre à jour le fichier .pro de notre projet, afin que Qt sache que nous avons un fichier .ui et qu'il faudra générer le code source correspondant. Vous n'appellerez pas uic directement, c'est Qt qui le fera pour vous avant la compilation.
  2. Puis, nous adapterons le code source dans notre application afin d'ouvrir la fenêtre générée avec Qt Designer.


Préparer notre projet à générer le code



La première étape consiste à mettre à jour le fichier .pro de votre application pour lui faire comprendre que votre programme utilise désormais un .ui créé avec Qt Designer.



Le fichier .pro a normalement été automatiquement généré par qmake -project.

Vous avez 2 possibilités :
  • Soit vous retapez qmake -project dans la console. Dans ce cas, Qt découvrira automatiquement la présence d'un fichier .ui dans le dossier du projet, et modifiera le fichier .pro en conséquence.
  • Soit vous éditez à la main le fichier .pro avec un éditeur de texte, et vous rajoutez la ligne surlignée dans le code ci-dessous :

    Code : Autre
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    ######################################################################
    # Automatically generated by qmake (2.01a) lun. 2. juin 12:00:20 2008
    ######################################################################
    
    TEMPLATE = app
    TARGET = 
    DEPENDPATH += .
    INCLUDEPATH += .
    
    # Input
    FORMS += calculatrice.ui
    SOURCES += main.cpp


    Comme vous pouvez le voir, j'ai ajouté la ligne FORMS. Elle donne la liste des fichiers .ui utilisés par votre application.


Voilà, c'est bon. :)
Maintenant, faites un qmake. Cela aura pour effet de préparer votre code à la compilation en générant un makefile, comme je vous l'avais expliqué au tout début de la partie sur Qt.

Le fichier ui_calculatrice.h sera généré par uic au moment de la compilation, lorsque vous taperez make (ne le faites pas maintenant, nous le ferons plus tard).
Vous n'avez rien d'autre à faire, vous n'avez pas besoin d'appeler uic vous-mêmes. Le programme uic sera automatiquement appelé juste avant la compilation.



Utiliser la fenêtre dans notre application



Il nous reste une importante étape : modifier le code source de notre application pour ouvrir la fenêtre créée sous Qt Designer.
Et là, nous avons le choix. Nous pouvons utiliser la fenêtre de 3 manières différentes, de la plus simple à la plus compliquée (la plus compliquée étant la meilleure bien sûr :D ) :

  • Utilisation directe
  • Utilisation avec un héritage simple
  • Utilisation avec un héritage multiple

Je vais vous décrire chacune de ces 3 méthodes. :)
Vous verrez que la dernière, bien que plus complexe, est la plus pratique et la plus souple.


Utilisation directe



Avantages : technique très simple à mettre en oeuvre, à peine quelques lignes à écrire.
Défauts : pas de possibilité de personnaliser la fenêtre, ni d'écrire des slots personnalisés. La fenêtre est "figée".



La technique la plus simple, mais la moins puissante, consiste à utiliser directement la fenêtre générée.
On va supposer que votre programme n'est constitué que d'un main(). Ajoutez les lignes surlignées :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <QApplication>
#include <QtGui>
#include "ui_calculatrice.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget *fenetre = new QWidget;
    Ui::FenCalculatrice ui;
    ui.setupUi(fenetre);

    fenetre->show();

    return app.exec();
}


Dans un premier temps, on inclut le fichier ui_calculatrice.h qui sera généré par uic juste avant la compilation.

Ensuite, on fait comme si on créait une nouvelle fenêtre en créant un nouvel objet de type QWidget (ligne 9).

Au lieu d'afficher cette fenêtre directement, on la précharge avec le contenu que l'on a dessiné dans Qt Designer. Pour cela, on crée un objet de type Ui::FenCalculatrice (où "FenCalculatrice" est le nom que vous avez donné à votre fenêtre dans Qt Designer). On appelle setupUi(fenetre) pour dessiner le contenu de la fenêtre avec l'interface réalisée sous Qt Designer.

On peut ensuite ouvrir la fenêtre avec fenetre->show(); comme d'habitude. :)

Compilez maintenant avec make en ligne de commande. Le programme uic sera appelé en arrière-plan pour que le fichier ui_calculatrice.h soit généré. Puis, l'ensemble des fichiers .cpp et .h seront compilés comme d'habitude.
Admirez ensuite le programme ainsi généré :

Mini calculatrice


Ca marche ! :D
Vous noterez toutefois qu'il y a un défaut : notre fenêtre s'affiche, c'est bien beau, mais elle ne réagit au clic sur le bouton "=". En effet, la méthode que nous venons de voir est très simple, mais elle a un énorme défaut : nous ne pouvons pas créer nos propres slots pour personnaliser un peu le code de la fenêtre.

Les techniques suivantes que nous allons voir nous permettent de le faire, et sont donc bien plus souples.


Utilisation avec un héritage simple



Avantages : on peut personnaliser la fenêtre et écrire nos propres slots.
Défauts : il faut utiliser le préfixe "ui" devant les noms de tous les widgets pour pouvoir les utiliser.


Nous allons hériter de la fenêtre créée avec Qt Designer. Pour faire cela, nous allons créer une nouvelle classe dans notre projet intitulée "FenCalculatrice" (du même nom que la fenêtre créée sous Qt Designer, oui oui). Créez un .cpp et un .h.

Au final, votre projet devrait comporter les fichiers suivants :

  • main.cpp
  • FenCalculatrice.h
  • FenCalculatrice.cpp


Refaites un qmake -project pour mettre à jour le fichier .pro de votre projet, afin de vous assurer que les nouveaux fichiers FenCalculatrice.h et FenCalculatrice.cpp seront bien compilés.

Définissez le fichier FenCalculatrice.h comme ceci :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef HEADER_FENCALCULATRICE
#define HEADER_FENCALCULATRICE

#include <QtGui>
#include "ui_calculatrice.h"

class FenCalculatrice : public QWidget
{
    Q_OBJECT

    public:
        FenCalculatrice(QWidget *parent = 0);

    private slots:
        /* Insérez les prototypes de vos slots personnalisés ici */

    private:
        Ui::FenCalculatrice ui;
};


#endif


On inclut "ui_calculatrice.h" pour pouvoir utiliser la fenêtre créée avec Qt Designer.
On crée une classe FenCalculatrice héritant de QWidget. Ehhh oui, il faut hériter du même type que la fenêtre créée sous Qt Designer (qui était un QWidget si vous vous souvenez bien).

On crée un constructeur classique.
On déclare un objet "ui" de type Ui::FenCalculatrice. Ca c'est la particularité. L'objet ui contiendra tous les widgets de la fenêtre, vous allez voir.


Maintenant, on va implémenter le constructeur dans FenCalculatrice.cpp. Là, vous allez voir, c'est ultra-simple :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include "FenCalculatrice.h"

FenCalculatrice::FenCalculatrice(QWidget *parent) : QWidget(parent)
{
    ui.setupUi(this); // A faire en premier

    /*
    Personnalisez vos widgets ici si nécessaire
    Réalisez des connexions supplémentaires entre signaux et slots
    */
}


Tout ce que vous avez à faire, c'est un ui.setupUi(this) pour créer le contenu de la fenêtre.
Il faut faire cela en premier dans le constructeur. Ensuite, libre à vous de personnaliser les widgets et de créer des connexions supplémentaires entre des signaux et des slots.

Particularité : tous les widgets sont accessibles en faisant ui.nomDuWidget .
Par exemple, on peut changer le texte du bouton comme ceci :

Code : C++
1
2
3
4
5
6
7
8
#include "FenCalculatrice.h"

FenCalculatrice::FenCalculatrice(QWidget *parent) : QWidget(parent)
{
    ui.setupUi(this);

    ui.boutonEgal->setText("Egal");
}


Le nom du bouton "boutonEgal", nous l'avons défini dans Qt Designer tout à l'heure (propriété objectName de QObject). Retournez voir le petit tableau un peu plus haut pour vous souvenir de la liste des noms des widgets de la fenêtre.


Bon en général vous n'aurez pas besoin de personnaliser vos widgets, vu que vous avez tout fait sous Qt Designer. Mais si vous avez besoin d'adapter leur contenu à l'exécution (pour afficher le nom de l'utilisateur par exemple), il faudra passer par là.

Maintenant ce qui est intéressant surtout, c'est d'effectuer une connexion :

Code : C++
1
2
3
4
5
6
7
8
#include "FenCalculatrice.h"

FenCalculatrice::FenCalculatrice(QWidget *parent) : QWidget(parent)
{
    ui.setupUi(this);

    connect(ui.boutonEgal, SIGNAL(clicked()), this, SLOT(calculerOperation()));
}


N'oubliez pas à chaque fois de mettre le préfixe "ui" devant chaque nom de widget !


Ce code nous permet de faire en sorte que le slot calculerOperation() de la fenêtre soit appelé à chaque fois que l'on clique sur le bouton.

Il ne vous reste plus qu'à adapter votre main pour appeler la fenêtre comme une fenêtre classique :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <QApplication>
#include <QtGui>
#include "FenCalculatrice.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    FenCalculatrice fenetre;
    fenetre.show();

    return app.exec();
}



La méthode que nous venons de voir est très pratique et on peut faire tout ce qu'on veut avec, mais il faut écrire le préfixe "ui" devant le nom du widget à chaque fois.
Si vous voulez évitez d'avoir à écrire "ui", il va falloir faire un héritage multiple...


Utilisation avec un héritage multiple



Avantages : on peut personnaliser la fenêtre, écrire nos propres slots, et on n'a pas besoin de mettre le préfixe "ui" devant chaque nom de widget.
Défauts : il faut faire un héritage multiple, une technique un peu plus complexe que l'héritage classique.



L'héritage multiple est une technique complexe du C++ que je ne vous ai pas enseignée jusqu'alors dans le cours. Il faut dire qu'on l'utilise rarement et, bien que cette technique soit puissante, elle est considérée comme trop complexes par certains nouveaux langages (Java, Ruby...) qui ont décidé de ne pas gérer l'héritage multiple.

Bon, le principe c'est quoi ? A priori c'est tout bête : c'est une classe qui hérite de 2 classes (ou plus !).
Dans notre cas, il faut que l'on hérite à la fois de QWidget (le type de la fenêtre) et de Ui::FenCalculatrice (la fenêtre créée sous Qt Designer) !

Héritage multiple


En pratique, dans la déclaration de la classe (fichier FenCalculatrice.h), ce qui change c'est la ligne 7 :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#ifndef HEADER_FENCALCULATRICE
#define HEADER_FENCALCULATRICE

#include <QtGui>
#include "ui_calculatrice.h"

class FenCalculatrice : public QWidget, private Ui::FenCalculatrice
{
    Q_OBJECT

    public:
        FenCalculatrice(QWidget *parent = 0);

    private slots:
        /* Insérez les prototypes de vos slots personnalisés ici */
};


#endif


La seule ligne qui change a été surlignée, c'est celle de déclaration de la classe. On hérite de QWidget et de Ui::FenCalculatrice à la fois.
Vous noterez qu'on n'a plus besoin de définir un objet "ui" de type Ui::FenCalculatrice cette fois.

Dans le fichier .cpp, c'est pareil sauf que maintenant vous pouvez enlever tous les préfixes "ui" :

Code : C++
1
2
3
4
5
6
7
8
#include "FenCalculatrice.h"

FenCalculatrice::FenCalculatrice(QWidget *parent) : QWidget(parent)
{
    setupUi(this);

    connect(boutonEgal, SIGNAL(clicked()), this, SLOT(calculerOperation()));
}



Personnaliser le code et utiliser les Auto-Connect



Les fenêtres créées avec Qt Designer bénéficient du système "Auto-Connect" de Qt. C'est un système qui crée les connexions tout seul.

Par quelle magie ?
Il vous suffit en fait de créer des slots en leur donnant un nom qui respecte une convention.

Prenons le widget boutonEgal et son signal clicked(). Si vous créez un slot appelé on_boutonEgal_clicked() dans votre fenêtre, ce slot sera automatiquement appelé lors d'un clic sur le bouton.

La convention à respecter est représentée sur le schéma ci-dessous :

Auto-Connect



Essayons d'utiliser l'Auto-Connect dans notre programme. Je me base ici sur un héritage multiple.

Voici le .h :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#ifndef HEADER_FENCALCULATRICE
#define HEADER_FENCALCULATRICE

#include <QtGui>
#include "ui_calculatrice.h"

class FenCalculatrice : public QWidget, private Ui::FenCalculatrice
{
    Q_OBJECT

    public:
        FenCalculatrice(QWidget *parent = 0);

    private slots:
        void on_boutonEgal_clicked();
};


#endif


... et le .cpp :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include "FenCalculatrice.h"

FenCalculatrice::FenCalculatrice(QWidget *parent) : QWidget(parent)
{
    setupUi(this);
}

void FenCalculatrice::on_boutonEgal_clicked()
{
    int somme = nombre1->value() + nombre2->value();
    resultat->setNum(somme);
}


Vous noterez qu'on n'a plus besoin de faire de connexion dans le constructeur. Ben oui, c'est le principe de l'Auto-Connect. :p
Comme vous le voyez, il suffit de créer un slot avec un nom particulier, et tout roule comme sur des roulettes !

Vous pouvez tester le programme, ça marche !

Mini calculatrice opérationnelle


Bon, j'avoue, je n'ai géré ici que l'addition. Mais je vais pas tout vous faire non plus hein. :-°

Exercice (me dites pas que vous l'avez pas vu venir :p ) : complétez le code de la calculatrice pour effectuer la bonne opération en fonction de l'élément sélectionné dans la liste déroulante.

L'Auto-Connect est activé par défaut dans les fenêtres créées avec Qt Designer, mais vous pouvez aussi vous en servir dans vos autres fenêtres "faites main".
Il suffira d'ajouter la ligne suivante dans le constructeur de la fenêtre pour bénéficier de toute la puissance de l'Auto-Connect : QMetaObject::connectSlotsByName(this);

Q.C.M.

Quel est le nom du programme qui génère le code source correspondant à un fichier de fenêtre .ui ?
Que doit-on faire pour afficher l'aide sur une des propriétés d'un widget dans Qt Designer ?
Que doit-on faire pour changer le nom des widgets sous Qt Designer ?
Le signal envoi(int) est-il compatible avec le slot reception() ?
3 méthodes permettent d'utiliser une fenêtre créée sous Qt Designer dans son projet. L'une d'elles ne permet pas d'adapter le code de la fenêtre, ce qui fait qu'on ne peut pas créer de slots personnalisés. Laquelle ?
Quel est l'avantage de l'héritage multiple par rapport à l'héritage simple pour utiliser une fenêtre issue de Qt Designer ?
Lequel de ces slots est compatible avec l'Auto-Connect ?

Statistiques de réponses au QCM


Ceux qui croyaient que Qt Designer était un "programme magique qui allait réaliser des fenêtres tout seul sans avoir besoin de coder" en ont été pour leurs frais ! :pirate:

Pourtant, comme avec Qt Linguist, le processus de création de fenêtres de Qt Designer a été très bien pensé. Tout est logique et s'enchaîne de bout en bout, mais encore faut-il comprendre cette logique. J'espère vous y avoir aidé à travers ce chapitre.

J'ai profité de ce chapitre pour survoler la notion d'héritage multiple. Il y aurait à redire sur cette notion, mais c'est un peu complexe et on peut se contenter de retenir ce qui a été dit dans ce chapitre si on a juste besoin d'utiliser des fenêtres créées avec Qt Designer.
Si vous voulez en savoir plus (et je vous y encourage), il vous faudra chercher d'autres cours sur le web traitant de l'héritage multiple en C++.


Entraînez-vous à utiliser quelques fenêtres créées avec Qt Designer, et en particulier à créer des slots personnalisés.
Tant qu'à faire, je vous conseille de vous servir de l'Auto-Connect. Une fois qu'on y a goûté on ne peut plus s'en passer. :p
Chapitre précédent Sommaire Chapitre suivant

Informations sur le tutoriel

Retour en haut Retour en haut

Créé : Le 18/09/2007 à 17:13:58
Modifié : Le 20/07/2009 à 16:29:41
Avancement : 100%

49 commentaires