P
'
t
i
t
e
C
h
a
t
t
e
 
spacer~ IT'S NOT A BUG, IT'S A FEATURE Articles | Connexion
 
~Introduction à PyQT

Précédent  
  Python  
  Suivant
 Présentation

La bibliothèque d'éléments graphiques QT apparaît en 1994. Écrite en C++ et produite par la société Trolltech, cette librairie est aujourd'hui largement répandue et se trouve au cour de logiciels Open Source tels que KDE. Découvrons comment employer QT au sein de nos programmes Python.
 Sommaire


 Introduction

La bibliothèque QT, dont la dernière version possède le numéro 3.0, existe sous la forme de deux entités distinctes. La première correspond à la version commerciale de la bibliothèque. Son utilisation nécessite l'achat de licences et se trouve nécessaire pour la réalisation d'applications elles-mêmes commerciales. La seconde forme de QT se voit régie par la licence libre GPL. Dès lors que vous installez cette variation de la bibliothèque, vous vous trouvez en mesure d'écrire des applications libres en profitant de la puissance de cette bibliothèque.

Puisque QT a été écrite originellement pour le langage C++, les programmeurs Python doivent faire appel à un outil supplémentaire afin de lier leurs programmes à la bibliothèque. Un tel outil de lien se nomme un "bindings set". Celui que nous utiliserons se nomme PyQT. Le site Internet http://www.riverbankcomputing.co.uk/pyqt/ vous offrira toutes les informations relatives à cet outil.

L'installation et l'utilisation de PyQT ne posent aucun problème et la compatibilité offerte se révèle impressionnante puisque PyQT fonctionne avec les versions de QT numérotées de 1.43 à 3.0.4, QT Non Commercial, Qtopia et Python de 1.5 à 2.2.1.

Enfin, il convient de remarquer que QT ne propose pas seulement, à l'instar de wxPython, des composants graphiques. La bibliothèque contient également des modules de gestion du XML, de SQL, des Sockets.


 Hello World

Afin de ne pas perdre les bonnes habitudes, nous allons commencer notre découverte de PyQT par un simple Hello World. Un programme QT doit impérativement posséder une instance de la classe QApplication. Cette instance garantit l'exécution du programme en gérant la boucle d'événements principale et propose de nombreuses fonctions utilitaires. Notez pour la suite que l'instance de QApplication se voit toujours accessible par l'entremise de la variable globale qApp. Quoi qu'il en soit, voici la procédure à suivre pour créer une nouvelle application QT :

import sys
from qt import *
app = QApplication(sys.argv)
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
La transmission des paramètres de la ligne de commande à l'application permet à l'utilisateur de spécifier diverses options communes à tous les programmes QT. Nous ne décrirons pas ces options en détail (RTFM pour ainsi dire), mais nous reviendrons un peu plus loin sur un exemple intéressant.

Lorsque l'application est créée, celle-ci ne connaît pas le composant (ou widget) principal de l'application. Ce widget particulier détermine la durée de vie de l'application : lorsqu'il est détruit, l'application se termine.

Avant de procéder à la détermination du widget principal, nous devons bien entendu en créer un. L'exemple suivant crée un simple bouton nanti de l'étiquette "Hello World" :

btnHello = QPushButton("Hello World", None)
       
      
JextCopier dans Jext
Le second paramètre donné au constructeur désigne le parent de l'objet. Puisque ce widget a été désigné comme étant le widget principal de l'application, il ne possède aucun parent. Une fois le bouton créé, nous sommes en mesure de définir le composant principal puis d'afficher le bouton (si vous oubliez cette opération, vous ne verrez absolument rien à l'écran) :

app.setMainWidget(btnHello)
btnHello.show()
       
      
JextCopier dans Jext
Il ne vous reste qu'à exécuter le script et à admirer le magnifique. hélas ! Rien ne se produit. Le programmeur doit en effet demander explicitement le démarrage de l'application en exécutant la boucle principale de l'application. Pour ce faire, un simple appel de méthode suffit :

app.exec_loop()
       
      
JextCopier dans Jext
Le programme est à présent complet et fonctionne parfaitement, bien que le bouton soit particulièrement inactif. Le composant principal de l'application peut désigner tout objet graphique, soit toute instance d'une classe héritant de QWidget. Néanmoins, dans un "vrai" programme, le composant principal désigne souvent une fenêtre complète et non un simple bouton. Essayez également d'exécuter le script de la sorte :

./helloqt.py -style=platinum
       
      
JextCopier dans Jext
Il s'agit de l'un des fameux arguments interprétés par QApplication. Celui-ci modifie le style graphique de l'application et les valeurs possibles sont motif, windows et platinum.


 Slots et signaux

QT octroie l'opportunité de gérer les événements de chaque widget par l'intermédiaire d'un système de "slots" et de "signaux". Plus clairement, un signal détermine un événement et un slot un réceptacle pour les événements. Ainsi, pour traiter l'événement de clic sur un bouton "Quitter", nous lierons le signal "clicked()" au slot "quit()". Sachez qu'un slot peut correspondre à un signal (le signal est alors transmis à un autre signal).

Avec PyQT, nous devons distinguer les slots et signaux QT (natifs) des slots et signaux Python. La différence se révèle ténue, mais existe néanmoins. Examinons d'abord l'utilisation d'un couple slot/signal natif. Le script helloqt2.py présente une application offrant deux boutons : un bouton "Hello" affichant un message et employant un slot Python, et un bouton "Quit" employant un slot QT.

Voici le code source traitant le bouton "Quit" :

quit = QPushButton("Quit", self, "quit")
self.connect(quit, SIGNAL("clicked()"), qApp, SLOT("quit()"))
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Ici, la référence self désigne une instance d'un widget QVBox qui permet d'afficher des composants verticalement les uns par rapport aux autres. Notre exemple définit une nouvelle classe MyWidget héritant de QVBox. Ce nouveau widget contient lui-même les deux boutons cités précédemment. Il vous suffit de comprendre que tous les composants possèdent la méthode connect(), en vérité définie comme statique au sein de la classe QObject.

Dans l'exemple ci-dessus, nous lions le signal "clicked()" de l'objet "quit" au slot "quit()" de l'objet "qApp".

Souvenez-vous que qApp désigne toujours l'application. A tout moment le programmeur peut décider de déconnecter un signal de son slot en appelant la méthode disconnect() avec les mêmes arguments. Cette connexion activera le slot qApp.quit() lorsque le signal quit.clicked() sera émis. La notation de connect() employée ici n'est valable que lorsque le slot est un slot QT (pour utiliser un signal Python il suffit de changer SIGNAL en PYSIGNAL).

Le bouton "Hello" emploie un slot Python. La connexion d'un slot Python se réalise de manière générale ainsi :

self.connect(obj, SIGNAL("signal"), slot)
       
      
JextCopier dans Jext
Un slot peut correspondre à une fonction ou à une méthode (préfixée par le nom de l'objet). Ainsi dans notre programme :

hello = QPushButton("Hello", self, "hello")
self.connect(hello, SIGNAL("clicked()"), self.popupHello)
       
      
JextCopier dans Jext
La méthode self.popupHello() doit accepter un paramètre correspondant à l'objet ayant connecté le signal et le slot. Ici, le paramètre désignera l'instance de MyWidget tandis que si nous avions appelé hello.connect(), le paramètre aurait désigné le bouton lui-même.

La réalisation d'interfaces avec PyQT peut se voir considérablement simplifiée en utilisant l'outil QT Designer délivré avec la bibliothèque QT. Nous examinerons cet outil le mois prochain.



par Romain Guy
romain.guy@jext.org
http://www.jext.org
Dernière mise à jour : 14/10/2006


Précédent  
  Python  
  Suivant

 
#ProgX©2005 Mathieu GINOD - Romain GUY - Erik LOUISE