I. Objectif du projet

L'objectif du projet va être de créer une application de gestion de bateaux, pour ne pas reprendre l'exemple bateau d'un petit éditeur de textes. Ce sera un simple CRUD qui va permettre de créer, éditer et supprimer une liste de bateaux stockée dans une base de données SQLite. On verra ainsi un certain nombre de composants basiques de Qt comme un tableau, un widget de texte simple, un label et des boutons, ainsi que des concepts de base de Qt comme les signaux et les composants orientésMVD (Modèle Vue Délégué).

Nous allons commencer par la création de l'écran en utilisant QtCreator.

II. Création de l'écran

L'installation de QtCreator ne devrait pas poser trop de problèmes et se passe bien sur de nombreuses plateformes. Pour partir sur de bonnes bases nous allons donc créer un nouveau projet en utilisant le menu Fichier -> Nouveau fichier ou projet ..., on arrive alors sur l'écran suivant, où l'on va choisir "Projet Qt4 vide" :

New project screen on QtDesigner

On choisit le nom du projet et son répertoire racine :

Image non disponible

Une fois le projet créé, nous allons construire notre premier écran, en réalisant un clic droit sur le projet :

Image non disponible

On choisit le type de fichier à rajouter, dans notre cas un nouvel écran :

Image non disponible

En choisissant parmi les templates de base proposés, le QGroupBox :

Image non disponible

On arrive sur l'interface de base suivante :

Image non disponible

Ensuite en utilisant le système de glisser-déposer, il devient simple de positionner les widgets que l'on veut ( un Model-Based Table Widget, un Label, trois Push Button et un Text Line) comme ceci :

Image non disponible

La prise en main de QtCreator est assez simple. Ainsi pour changer les valeurs par défaut "TextLabel", "PushButton", "GroupBox", il suffit de double cliquer sur le composant et modifier la valeur textuelle. Il est aussi possible, entre autres, de modifier le nom des variables pour chacun des composants utilisés de manière à avoir quelque chose de plus cohérent et compréhensible que push_Button1, push_button2 ...

III. Compilation et intégration dans une application existante

Une erreur à éviter est de croire que QtCreator va nous aider dans la suite des opérations. Cet environnement de développement est conçu à la base pour C++, ainsi les paramètres de compilation et de debogage ne peuvent être utilisés dans le cadre d'un développement avec PyQt.

En revanche il nous a permis d'aller très loin dans la création et dans l'utilisation de l'écran, il suffit d'utiliser le fichier .ui créé, dans notre cas groupbox.ui, et de l'utiliser directement avec un petit utilitaire appelé pyuic (dans notre cas pyuic4), fourni avec l'installation de PyQt, qui va transformer notre interface en code Python utilisable :

Image non disponible

Pour obtenir le code suivant :

Image non disponible

Ce code est généré. On pourrait donc s'attendre à ce qu'il ne soit pas lisible facilement mais le fait est qu'il est assez clairement organisé. Même si les variables n'ont pas des noms très explicites, il est possible, grâce à QtDesigner, de palier à ce manque. Il est aussi possible de prédéfinir un certain nombre de signaux.

Il s'agit maintenant de créer un fichier main.py qui va initialiser notre application, mettre en place cet écran et permettre de compléter notre interface pour :

  • mettre en place des actions liées aux boutons
  • insérer ou supprimer des lignes dans le tableau
  • etc.

Pour tester l'application, voici le contenu du fichier main.py :

Image non disponible

Pour expliciter un peu ces quelques lignes, voilà une petite liste des points importants :

  • l'application gérant l'écran étend la classe du composant, dans notre cas QGroupBox
  • on instancie alors le composant Ui_GroupBox et on complète son initialisation en appelant la méthode setupUi
  • la dernière partie permet de lancer l'application de manière autonome.

En lançant ce code (e.g. par la commande python main.py), l'écran suivant devrait s'afficher sans encombre :

Image non disponible

Il est bien sûr mieux de modifier les labels des composants et en le faisant (dans QtCreator), on peut voir la rapidité de propagation des modifications de l'interface que permet PyQt. Ainsi en modifiant les labels dans QtCreator, et en relançant pyuic on régénère l'écran pour obtenir :

Image non disponible

Ce cycle de déploiement rapide permet de faire des modifications et de les propager très rapidement à toute l'application. Nous allons maintenant parler des signaux, un des concepts les mieux conçus dans Qt. Ce concept permet à un composant d'envoyer un signal vers un autre composant, plus précisément vers une partie dédiée receveuse du composant appelée slot et de recevoir des signaux dans ses slots. Le framework Qt permet alors de connecter un signal d'un composant avec un slot.

Le principe est mieux illustré avec un exemple : un bouton "Save" est cliqué. Il doit transmettre cette information et communiquer non seulement avec le TextLine pour lui dire de se vider mais aussi avec le tableau pour mettre à jour ses données, ou encore appeler une de ses méthodes.

Avec Qt le bouton va ainsi émettre trois signaux différents pour chacune des actions nécessaires et vers chacun des composants concernés. Ainsi, par exemple, pour montrer que les boutons "Delete" et "New" vont vider le composant d'édition, on écrira les connexions suivantes :

Image non disponible

Il reste un dernier point à aborder, mais qui montre encore une facette de Qt qui fait la particularité de ce framework, c'est celui du remplissage du tableau - TableView. Ce composant est basé sur le principe du Modèle Vue Délégué - la vue étant le composant TableView, il nous manque le modèle.

Pour rester simple et ne pas commencer par créer son propre modèle soi-même j'ai décidé d'utiliser comme modèle le QSqlTableModel, qui permet, moyennant une QSqlDatabase (représentant une connexion à une base de données), de montrer le contenu d'une table.

J'ai donc mis en place une base de données SQLite avec SQLAlchemy, dont le code sera joint, pour rajouter facilement un nouvel objet et obtenir le code suivant :

Image non disponible

et un résultat assez convaincant :

Image non disponible

IV. En conclusion

Ce petit article introductif a pour but de montrer ce que l'on peut faire en Python avec Qt pour développer rapidement une application avec un client lourd, et ce sans la lourdeur d'un framework complexe ou les difficultés de prise en main de certaines librairies. PyQt est un binding et pas une implémentation complète à la différence de QtJambi pour Java, mais il mérite le détour et est une alternative visuellement agréable à TkInter.

V. Pour aller plus loin...

Pour aller plus loin il y a l'excellent livre de Mark Summerfield : Rapid gui programming with Python and Qt
et bien sûr n'hésitez pas à poser des questions sur les forums, à me contacter, ou à consulter les quelques liens ci-après :

et enfin les fichiers présentés dans ce tutoriel, pour pouvoir améliorer encore ce petit projet :

ShipHolder.zip

VI. Remerciements...

Je tiens à remercier dourouc05 responsable Qt pour son aide dans la rédaction de cet article ainsi que jacques_jean et Benj. pour leurs relectures attentives.