comme outils de développement rapide d’application graphique
Python est un langage interprété et orienté objet. Il bénéficie d’une gestion automatique de la mémoire via un ramasse-miettes (garbage collector) et les variables sont typées dynamiquement.
Pour toutes ces raisons, un programme écrit en Python est souvent bien plus court en terme de lignes de code que son équivalent C++ ou C. L’absence de phase de compilation ajoute encore au confort d’utilisation.
Python rend les programmes plus simples et plus faciles à écrire, ce qui en fait un bon langage pour le développement rapide d’application.
PyQt permet de lier le langage Python avec la bibliotèque Qt. Qt est un cadriciel (framework) qui permet de créer des interfaces graphiques multiplateformes. Le framework Qt offre également beaucoup d’autres services mais ce document s’arrête sur la manière de dessiner des interfaces graphiques avec les outils Qt.
Afin d’illustrer l’utilisation de Python et de PyQt, voici une application de carnet d’adresses qui permet d’enregistrer des personnes et leurs coordonnées dans une liste.
Elle est écrite en 150 lignes de codes et respecte le motif de conception MVC (Modèle, Vue, Contrôleur).
Un outil de dessin d’interface comme Qt Designer apporte beaucoup d’avantages :
Pour créer l’application il faut une fenêtre principale, choisissez "Main Window".
Choisissez les options pas défaut pour obtenir une fenêtre avec une barre
de menu standard. Modifiez ensuite les propriétés name
en Main
et caption
avec "carnet d’adresses" pour donner un titre à votre fenêtre.
Il faut maintenant créer les composants graphiques nécéssaires pour l’application.
Renommez ensuite ces éléments avec des noms appropriés. Il est nécessaire d’utiliser des noms logiques afin de pouvoir accéder aux composants.
Il manque encore la touche finale qui va permettre aux composants de bien se comporter en cas de redimensionnement de la fenêtre. Selectionnez un label et une ligne d’entrée de texte et choisissez un "layout horizontal". Répétez l’opération pour chaque paire label/ligne d’entrée de texte.
Sélectionnez maintenant les paires label/ligne d’entrée de texte et les boutons "ajouter", "supprimer" et choisissez un "layout vertical".
Faites un "horizontal layout" avec les deux autres boutons, puis un "vertical layout" avec le composant résultant et la liste. Vous pouvez ensuite faire un "horizontal layout (with splitter)" avec les deux composants restant ou simplement un "horizontal layout". Pour que le composant final prenne tout l’espace disponible il faut faire un "grid layout" sur la fenêtre principale. Pour finir, désactivez le bouton "modifier".
Vous pouvez encore définir une taille minimale aux composants label
afin d’avoir
les lignes d’entrée de texte bien alignées.
Il vous faut maintenant sauvegarder votre travail sous le nom main.ui
. Les fichiers
".ui" sont des fichier XML de description d’interface.
Afin de pouvoir utiliser les informations du fichier ".ui"
de Qt Designer, il faut le traduire en Python. C’est le but
du logiciel pyuic
.
Il faut donc faire en ligne de commande : pyuic main.ui > main.py
L’objet client n’est qu’une structure de données qui permet de stocker les informations le concernant :
class client: def __init__(self,nom,prenom,rue,npa,email): self.nom=nom self.prenom=prenom self.rue=rue self.npa=npa self.email=email
Le carnet d’adresses sert à lire le fichier de clients et offre les méthodes nécessaires à sa modification, à sa représentation et à sa sauvegarde :
class carnet: def __init__(self,filename): self.clients = [] # restauration du carnet de clients depuis le fichier "filename" self.filename=filename if(os.path.exists(filename)): f = file(filename,'r') self.clients = pickle.load(f) f.close() # sauver la liste de clients dans le fichier def sauver(self): f = file(self.filename,'w') pickle.dump(self.clients,f) f.close() def ajouterClient(self, c): self.clients.append(c) def remplacerClient(self,index,c): self.clients[index]=c def client(self,indice): return self.clients[indice] def supprimer(self,indice): del self.clients[indice] # trie les clients selon la fonction de comparaison "sortFunc" def trier(self): self.clients.sort(self.sortFunc) # fonction de tri sur les noms des clients def sortFunc(self,x,y): return cmp(string.lower(x.nom),string.lower(y.nom)) # représentation des clients sous forme de liste pour l’affichage def listerClients(self): return [repr(client) for client in self.clients] def __repr__(self): return "\n".join(self.listerClients())
#!/usr/bin/python # -*- coding: utf8 -*- import sys import string import pickle import os from qt import * from main import * class app: index=-1 def __init__(self,args): # l’application Qt self.qtapp=QApplication(args) # création du carnet self.c = carnet('carnet.obj') # création de la fenêtre principale self.win=Main() # affichage de la liste des clients dans la fenêtre self.updateList() # affichage de la fenêtre self.win.show() # connection SLOT/SIGNAL de Qt self.qtapp.connect(self.win.fileSaveAction,SIGNAL("activated()"), self.c.sauver) self.qtapp.connect(self.win.fileExitAction,SIGNAL("activated()"),self.qtapp,SLOT("quit()")) self.qtapp.connect(self.win.ajouter,SIGNAL("clicked()"), self.ajouter) self.qtapp.connect(self.win.modifier,SIGNAL("clicked()"), self.modifier) self.qtapp.connect(self.win.supprimer,SIGNAL("clicked()"), self.supprimer) self.qtapp.connect(self.win.trier,SIGNAL("clicked()"), self.trier) self.qtapp.connect(self.win.liste,SIGNAL("highlighted(int)"), self.selectionListe) self.qtapp.connect(self.qtapp, SIGNAL("lastWindowClosed()"), self.qtapp, SLOT("quit()")) self.qtapp.exec_loop() # création d’un nouveau client en utilisant les champs courants de la fenêtre def newClient(self): c = client( self.win.nom.text().ascii(), self.win.prenom.text().ascii(), self.win.rue.text().ascii(), self.win.npa.text().ascii(), self.win.email.text().ascii() ) return c # bouton ajouter def ajouter(self): self.c.ajouterClient(self.newClient()) i=self.index self.updateList() self.win.liste.setSelected(i,True) # mettre la liste à jour def updateList(self): self.win.liste.clear() self.win.liste.insertStrList(self.c.listerClients()) # quand un client est selectionné dans la liste def selectionListe(self,index): self.index = index self.win.nom.setText(self.c.client(index).nom) self.win.prenom.setText(self.c.client(index).prenom) self.win.rue.setText(self.c.client(index).rue) self.win.npa.setText(self.c.client(index).npa) self.win.email.setText(self.c.client(index).email) self.win.modifier.setEnabled(True) # bouton supprimer def supprimer(self): if( self.index>=0 ): i=self.index self.c.supprimer(self.index) self.updateList() self.win.liste.setSelected(i,True) # bouton modifier def modifier(self): if( self.index>=0 ): self.c.remplacerClient(self.index,self.newClient()) i=self.index self.updateList() self.win.liste.setSelected(i,True) # bouton trier def trier(self): self.c.trier() self.updateList() self.index=-1 self.win.modifier.setEnabled(False) def main(args): mapp = app(args) if __name__=="__main__": main(sys.argv)
Python et PyQt forment un excellent couple pour développer rapidement des applications graphiques multiplateformes. L’intégration de Qt dans Python par PyQt est vraiment excellente. On dirait presque qu’il s’agit du langage natif de Qt.
La licence d’utilisation de PyQt est liée à la version de Qt utilisée. Avec la version 4 de Qt on devrait pouvoir réaliser des applications pour Microsoft Windows sous licence GPL.