Tutoriel sur la programmation des interfaces graphiques avec le Framework Python Wx


Télécharger Tutoriel sur la programmation des interfaces graphiques avec le Framework Python Wx

★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Télécharger aussi :


Tutoriel sur la programmation des interfaces graphiques avec le Framework Python Wx

...

I - Introduction

wxPython est une collection de modules Python réalisée sur la base des wxWidgets de wxWindows, un framework multi-plateformes écrit en C++. wxPython met à disposition des développeurs un nombre impressionnant de classes permettant de réaliser des interfaces homme machine (IHM) complètement indépendantes de l' OS sur lequel ils sont mis en oeuvre. Mais au delà, d'une simple IHM, wxPython fournit également des classes de haut niveau aussi diverses que les sockets réseau, le traitement de l'image ou encore l'interprétation HTML ou XML. Le seul inconvénient que j'ai pu trouver dans wxPython, c'est la difficulté, notamment pour quelqu'un qui connaît mal l'anglais, d'en approcher la documentation, qui, bien que très complète, est particulièrement mal adaptée à l'apprentissage. Le but de ce tutoriel n'est donc pas de décrire l'ensemble des classes wxPython, mais plutôt de donner des clés permettant au débutant de comprendre la philosophie des wxWidgets, et de naviguer facilement dans leur documentation. Ce tutoriel n'est pas non plus destiné à enseigner Python, dont la connaissance est un préalable pour pouvoir aborder wxPython. Tout au long de mes exemples, je vous renverrai sur la documentation anglaise extrêmement bien construite des wxWidgets. Vous verrez qu'à force, vous parviendrez à vous y retrouver, et en ferez peu à peu votre référence unique, bien que celle-ci soit réalisée à destination des programmeurs en C++. Il existe bien une documentation des classes spécifique à Python, mais moins bien articulée, et qui ne sera réellement utile qu'aux programmeurs connaissant déjà bien le produit.

II - Pré-requis

Vous devez avoir Python installé sur votre machine (personnellement c'est la version 2.4). Vous devez récupérer wxPython que vous trouverez sur le site wxpython. Faites attention de bien récupérer la version de wxPython qui correspond à celle du Python installé sur votre machine. Pour l'installation, utilisez la procédure qui correspond à votre système d'exploitation. Sous MS Windows l'installation est simplifiée par un programme qui automatise les procédures. Sous linux, il existe des packages pré-compilés pour les plus courantes des distributions. Personnellement, je travaille avec la distribution Ubuntu Hoary basée sur la Debian, et le système d'installation très performant de cette distribution est complètement transparent pour l'utilisateur. Pour le codage, on peut utiliser un éditeur de texte courant. Personnellement j'utilise tout simplement Idle qui est fourni avec Python. Vous trouverez les liens pour télécharger tous les codes source de ce tutoriel à la fin de celui-ci.

III - Premier programme (Bonjour tout le monde)

Je ne résisterai pas au plaisir de vous initier au toujours populaire «Bonjour tout le monde !» (« Hello world ! » en anglais) que tout enseignant d'un langage informatique se fait un devoir de servir à ses élèves...

Nous allons utiliser quatre classes de wxPython pour réaliser cet exemple:

  • La classe Frame qui fournit une fenêtre classique.
  • La classe Panel qui fournit un conteneur polyvalent pour y déposer des contrôles.
  • La classe StaticText qui fournit une étiquette sur laquelle on peut afficher du texte.
  • La classe App qui est la classe de base de toute application wxPython.

III.A - Fichier : Exemple1.py

Exemple1.py

01 #!/usr/bin/python

02 # -*- coding: iso-8859-15 -*-

04 import wx05

06 class Bonjour(wx.Frame):

07 def __init__(self, titre):

08 wx.Frame.__init__(self, None, 1, title = titre, size = (200, 100))

09 conteneur = wx.Panel(self, 1, size = self.GetClientSize())

10 etiquette = wx.StaticText(conteneur, 1, "Bonjour tout le monde !", style = wx.ALIGN_CENTRE)

11 etiquette.CentreOnParent()

13 class MonApp(wx.App):

14 def OnInit(self):

15 fen = Bonjour("Exemple 1")

16 fen.Show(True)

17 self.SetTopWindow(fen)

18 return True

20 app = MonApp()

21 app.MainLoop()

Résultat à l'exécution :

Le visuel de cette fenêtre peut être très différent sur votre machine, selon que son OS est MS Windows, Linux (selon le thème du bureau), ou MAC OS. La capture qui précède a été réalisée sous Linux Ubuntu Hoary en environnement gnome.

Décortiquons un peu ces lignes de code :

III.A.1 - Ligne 01

Cette ligne est indispensable sous Linux pour indiquer à l'OS où se situe l'interpréteur Python, et pour permettre un lancement du script par double-clic.

III.A.2 - Ligne 02

Cette ligne permet de faire prendre en compte par l'interpréteur les accentués et le sigle .

Ces deux premières lignes figurent toujours en début de mes scripts Python.

III.A.3 - Ligne 04

Depuis la version 2.4 de wxPython, l'espace de nom du module a changé, et se nomme tout simplement wx (l'ancien espace de nom wxPython.wx n'a été maintenu que pour assurer la compatibilité ascendante). Il suffit donc d'importer wx pour accéder aux wxWidgets. On pourrait également les importer sous la forme « from wx import * » afin d'éviter de systématiquement devoir préfixer chaque objet utilisé, mais je préfère personnellement utiliser le préfixe wx qui me permet de repérer immédiatement dans le code les références à wxPyth.

III.A.4 - Lignes 06 à 11

On construit une classe Bonjour dérivée du wxWidget wx.Frame (ligne 06) dont une instance sera la fenêtre qu'on veut afficher à l'écran.

Vous arrivez alors sur la documentation wxFrame où vous voyez que ce widget dérive de :

  • wxTopLevelWindow
  • wxWindow
  • wxEvtHandler
  • wxObject

Vous voyez aussi que sont listés un certain nombre de styles de fenêtre, et de processus d'événements par défaut. Retenez dans un premier temps, que les styles de fenêtre sont des styles supplémentaires par rapport à ceux de la classe parente wxWindow, et que les processus d'événements sont également supplémentaires par rapport à la classe parente wxEvtHandler. La rubrique intitulée Members liste les méthodes implémentées dans la classe. Celle qui nous intéresse est le constructeur de la classe dénommé wxFrame::wxFrame tel que défini en C++.

Si vous cliquez sur ce lien, vous arrivez à la documentation de cette méthode:



wxFrame()

Default constructor.

wxFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos =

wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE, const

wxString& name = "frame")

Il s'agit d'une méthode décrite à destination des programmeurs en C++. Il vous faut donc la transposer en méthode

Python pour pouvoir l'utiliser.

Cela donne ce qui suit :

wx.Frame(parent, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style =

wx.DEFAULT_FRAME_STYLE, name = 'frame')

Signification des paramètres :

parent

Il s'agit de la fenêtre qui doit accueillir la wx.Frame (le conteneur). None pour une wx.Frame en TopLevel

id

Un entier qui représente le Handle de la fenêtre. Indiquer la valeur -1 pour une attribution automatique par l'interpréteur.

title

Une chaîne de caractère qui sera affichée dans la barre de titre de la fenêtre.

pos

La position de la fenêtre (coordonnées supérieures gauche). La constante wx.DefaultPosition est prise par défaut, et correspond au tuple (-1, -1), qui est interprété par Python en fonction de l'OS.

size

La taille de la fenêtre (largeur, hauteur). La constante wx.DefaultSize est prise par défaut, et correspond au tuple (-1,

-1) qui laisse le choix à l'interpréteur d'une taille adaptée à l'OS.

style

Le style de la fenêtre, à choisir parmi les styles spécifiques à wx.Frame ou ceux de wx.Window dont wx.Frame dérive. Le style wx.DEFAULT_FRAME_STYLE pris par défaut correspond à l'assemblage des constantes de style wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION |

wx.CLOSE_BOX | wx.CLIP_CHILDREN. A noter que pour indiquer un assemblage de styles, il faut séparer chacune des constantes choisies par le trait vertical (Alt Gr + 6).

name

Le nom de la fenêtre. Je n'utilise pour ma part jamais ce paramètre qui peut être éventuellement utile sous MAC OS.

C'est donc aux lignes 07 et 08 que nous indiquerons les paramètres souhaités.

à la ligne 07, dans la méthode __init__() (habituelle des classes Python) de la classe Bonjour, nous indiquons les paramètres attendus pour instancier la classe. Ce peut être des paramètres attendus par la classe parente (wx.Frame), ou des paramètres nouveaux, propres à la classe dérivée. En l'occurrence, nous n'attendons que le paramètre «titre», qui correspond au paramètre «title» de wx.Frame. Les autres paramètres obligatoires ou que nous voulons alimenter par défaut pour wx.Frame seront indiqués à la ligne 08 dans la méthode d'initialisation __init__() de la classe parente. Hormis le mot clé «self» que nous retrouvons systématiquement en tête des arguments de méthodes de classes en Python, et qui établit explicitement un rapport entre la méthode et son propriétaire, nous avons défini par défaut que l'instance de wx.Frame créée par l'intermédiaire de la classe Bonjour ne devait pas avoir de parent (None), que son id devait être créé automatiquement (-1), que le texte à afficher dans sa barre de titre devait provenir du paramètre «titre» attendu pour sa classe fille, et que sa taille devait être d'une largeur de 200 pixels et d'une hauteur de 100 pixels. Les autres paramètres de cette Frame étant ceux définis par défaut. Ensuite, il nous reste à y placer le texte que nous voulons y voir affiché (Bonjour le monde !). Pour ce faire, à la ligne 09, nous créons, dans un premier temps, un conteneur destiné à recevoir le texte, sur la base d'un panneau wx.Panel, à placer dans notre fenêtre.

La rubrique Members donne accès au constructeur wxPanel::wxPanel qui se présente comme suit:

wxPanel()

Default constructor.

wxPanel(wxWindow* parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition, const wxSize&

size = wxDefaultSize, long style = wxTAB_TRAVERSAL, const wxString& name = "panel")

Transposé en Python, ça donne ceci :

wx.Panel(parent, id, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.TAB_TRAVERSAL, name ='panel')

Signification des paramètres :

parent

Il s'agit de la fenêtre qui doit accueillir le wx.Panel (le conteneur)

id

Un entier qui représente le Handle du Panel. Indiquer la valeur -1 pour une attribution automatique par l'interpréteur.

pos

La position du Panel (coordonnées supérieures gauche). La constante wx.DefaultPosition est prise par défaut, et correspond au tuple (-1, -1), qui est interprété par Python en fonction de l'OS.

Size

La taille du Panel (largeur, hauteur). La constante wx.DefaultSize est prise par défaut, et correspond au tuple (-1, -1) qui laisse le choix à l'interpréteur d'une taille adaptée à l'OS. style Le style du Panel, à choisir parmi les styles de la classe parente wx.Window (aucun style spécifique n'a été défini pour un wx.Panel). La constante de style wx.TAB_TRAVERSAL prise par défaut signifie que la touche TAB pourra être utilisée pour passer de contrôles en contrôles (pour les contrôles posés sur le Panel).

name

Le nom de la fenêtre. Je n'utilise pour ma part jamais ce paramètre qui peut être éventuellement utile sous MAC OS. Nous voyons donc que nous créons un wx.Panel dont l'identificateur est conteneur, le conteneur (parent) est le wx.Frame (référencé par le mot clé self), l'id est -1 (attribution automatique), et la taille (size) est calculée par la méthode GetClientSize() de la wx.Frame (mot clé self). Si on se réfère à la documentation à la rubrique wxFrame, on ne trouve aucune méthode de ce nom. C'est là l'avantage de la programmation orienté objet ; une classe hérite des méthodes de ses classes parentes. La plupart des méthodes de base des wxWidgets sont héritées de la classe wxWindow. On va donc consulter la documentation à la rubrique wxWindow, et on découvre alors la méthode wxWindow::GetClientSize.

wxSize GetClientSize() const

This gets the size of the window 'client area' in pixels. The client area is the area which may be drawn on by the programmer, excluding title bar, border, scrollbars, etc.

En français :

Cette méthode retourne la taille de la zone 'client' de la fenêtre, en pixels. La zone client est la zone sur laquelle le programmeur peut dessiner, à l'exclusion de la barre de titre, des bordures, des ascenseurs, etc.



Parameters

width (largeur) : Receives the client width in pixels.

height (hauteur) : Receives the client height in pixels.

wxPython note: In place of a single overloaded method name, wxPython implements the following methods:

GetClientSizeTuple() Returns a 2-tuple of (width, height)

GetClientSize() Returns a wxSize object

En détaillant sa documentation, on voit qu'il y a une particularité wxPython à cette méthode. Elle a été implémentée

de deux façons différentes:

GetClientSizeTuple() qui retourne un tuple composé de deux données, la largeur et la hauteur.

Cette méthode peut être très intéressante lorsqu'on a besoin de récupérer indépendamment l'une de l'autre les deux données. On peut alors le faire de la façon suivante :

largeur, hauteur = fenetre.GetClientSizeTuple()

GetClientSize() qui retourne les dimensions sous forme d'un objet wx.Size (il s'agit d'un objet englobant de façon monolithique les dimensions) pouvant être passé directement en paramètre size d'une fenêtre. C'est donc cette dernière méthode que nous utilisons à la ligne 09, de façon à ce que notre wx.Panel prenne toute la place de la zone client de la wx.Frame. On passe ensuite au message proprement dit qu'on veut afficher dans notre fenêtre. A la ligne 10, on crée un contrôle wx.StaticText, qui correspond à une simple étiquette sur laquelle on positionne le texte voulu.

On peut aller voir sa documentation en ligne, toujours au même endroit, et on peut changer de type de recherche en

choisissant une recherche par catégories, puis les contrôles, et parmi ceux-ci on clique sur wxStaticText.

On voit que cet objet dérive de :

  • wxControl
  • wxWindow
  • wxEvtHandler
  • wxObject

Son constructeur en C++ est le suivant:

wxStaticText()

Default constructor.

wxStaticText(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos =

wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = "staticText")

transposé en Python ça donne:

wx.StaticText(parent, id, label, pos = wx.DefaultPosition, size = wx.DefaultSize, style = 0, name = 'staticText')

Signification des paramètres :

parent

Il s'agit de la fenêtre qui doit accueillir le wx.StaticText (le conteneur). Comme nous plaçons ce contrôle sur notre wx.Panel, ce paramètre est passé sa référence, soit 'conteneur'.

id

Un entier qui représente le Handle du contrôle. Indiquer la valeur -1 pour une attribution automatique par l'interpréteur.

label

La chaîne de caractères que nous voulons voir affichée ('Bonjour le monde !'). pos

La position du contrôle (coordonnées supérieures gauche). La constante wx.DefaultPosition est prise par défaut, et correspond au tuple (-1, -1), qui est interprété par Python en fonction de l'OS.

size

La taille du contrôle (largeur, hauteur). La constante wx.DefaultSize est prise par défaut, et correspond au tuple (-1,

-1) qui laisse le choix à l'interpréteur d'une taille adaptée à l'OS.

style

Le style de la fenêtre, à choisir parmi les styles spécifiques à wx.StaticText ou ceux de wx.Window dont wx.StaticText dérive. Les styles spécifiques du contrôle sont des styles de présentation du texte dans le contrôle :

wx.ALIGN_RIGHT aligne le texte sur le bord droit du contrôle, wx.ALIGN_LEFT aligne le texte sur le bord gauche du contrôle, et wx.ALIGN_CENTRE place le texte au centre du contrôle (c'est ce dernier style que nous utilisons)... Il existe un style supplémentaire, wx.ST_NO_AUTORESIZE, qui empêche le contrôle de changer de taille quand le texte est modifié à l'aide de la méthode SetLabel().

name

Je ne reviens pas sur ce paramètre. Une fois notre contrôle texte créé, il nous reste à le centrer dans notre fenêtre. On fait ça à la ligne 11 à l'aide de la méthode CentreOnParent(), dérivée de la classe wxWindow et qui permet de centrer une fenêtre ou un contrôle dans son conteneur. Cette méthode prend un paramètre initialisé par défaut avec la constante wx.BOTH qui signifie un centrage à la fois vertical et horizontal. les deux autres valeurs acceptées sont wx.VERTICAL et wx.HORIZONTAL, qui n'ont pas besoin de précisions complémentaires.

III.A.5 - Lignes 13 à 18

C'est là la particularité de wxPython, celle qui nous oblige à pratiquement toujours développer en pur objet. Pour pouvoir lancer un interface graphique wxPython, on doit obligatoirement passer par un objet chargé de créer l'instance de la classe principale de l'interface (le Top Level). Cet objet doit lui-même être construit et dériver de la classe wx.App ; c'est ce qu'on fait à la ligne 13. La classe wx.App est initialisée différemment des classes Python classiques. Ce n'est pas la méthode __init__() qui doit être implémentée, mais une méthode OnInit() sans paramètre (sauf le mot clé self qui lui permet de s'autoréférencer) ; c'est ce qui est fait à la ligne 14. La séquence d'initialisation de la méthode OnInit() est alors toujours la même :

  • Création d'une instance de la fenêtre principale (ligne 15)
  • Affichage de la fenêtre par la méthode Show() dérivée de la classe wx.Window (ligne 16)
  • Désignation de la fenêtre en tant que principale par la méthode SetTopWindow() spécifique à la classe wx.App (ligne 17)
  • Retour de la valeur True marquant la fin de l'initialisation (ligne 18).

III.A.6 - Lignes 20 et 21

C'est là que démarre réellement notre application.

A la ligne 20, on crée une instance de l'application, qui elle-même crée une instance de notre fenêtre principale (classe Bonjour).

A la ligne 21 on démarre la boucle de gestion des évènements, qui permet au programme d'inter-agir avec son environnement.

Résumé On a vu dans ce chapitre:

  • Comment créer une fenêtre en wxPython
  • Comment positionner un contrôle dans une fenêtre
  • Comment consulter la documentation en ligne
  • Comment créer une application basée sur wxPython

C'est loin d'être suffisant, mais c'est un bon début...

IV - Gérer les évènements

Notre premier programme est magnifique d'équilibre, mais que ce passe-t-il lorsqu'on dimensionne notre fenêtre à la souris ?



28