Introduction à la programmation d'interface graphique avec Python

Les interfaces graphiques (GUI) sont au cœur de l'expérience utilisateur dans les applications modernes, permettant une interaction intuitive grâce à des éléments visuels. Python offre plusieurs bibliothèques pour développer des GUI, notamment Tkinter, PyQt et wxPython. Cet article explore les bases du développement GUI avec Python en utilisant wxPython comme exemple.

Notions fondamentales des GUI

Une interface graphique permet aux utilisateurs d'interagir avec un programme via des composants visuels comme les fenêtres, boutons et zones de texte. Elle remplace avantageusement les interfaces en ligne de commande en offrant une navigation plus accessible aux utilisateurs non techniques.

Bibliothèques GUI populaires pour Python

  • Tkinter : Intégré à la bibliothèque standard Python, idéal pour les projets simples et l'apprentissage initial.
  • PyQt/PySide : Basé sur le framework Qt, offfrant une large gamme de widgets et de fonctionnalités avancées.
  • wxPython : Construit au-dessus de wxWidgets, fournissant des composants natifs multiplateformes.

Configuration de wxPython

Pour commencer avec wxPython, l'installation se fait via le gestionnaire de paquets :

pip install wxPython

Création d'une application wxPython de base

Voici une première approche utilisant une classe dérivée de wx.App :

import wx

class MonApplication(wx.App):
    def OnInit(self):
        ma_fenetre = wx.Frame(None, title="Mon Programme", size=(400, 300))
        ma_fenetre.Show()
        return True

if __name__ == "__main__":
    application = MonApplication(False)
    application.MainLoop()

Initialisation simplifiée

Une alternative plus directe pour les applications simples :

import wx

def demarrer():
    appli = wx.App(False)
    fenetre = wx.Frame(None, title="Exemple Minimal", size=(350, 250))
    fenetre.Show()
    appli.MainLoop()

demarrer()

Personnalisation de la fenêtre principale

La classe wx.Frame permet de configurer la fenêtre principale :

import wx

class FenetrePrincipale(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        self.SetTitle("Application Personnalisée")
        self.SetSize(450, 350)
        
        panneau = wx.Panel(self)
        etiquette = wx.StaticText(panneau, label="Bienvenue dans l'application", pos=(120, 80))

if __name__ == "__main__":
    appli = wx.App(False)
    fenetre = FenetrePrincipale(None)
    fenetre.Show()
    appli.MainLoop()

Affichage de texte statique

Le widget wx.StaticText sert à afficher des informations non modifiables :

import wx

class FenetreAvecTexte(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        panel = wx.Panel(self)
        wx.StaticText(panel, label="Message d'information", pos=(15, 15))

if __name__ == "__main__":
    app = wx.App(False)
    frame = FenetreAvecTexte(None, title="Démonstration StaticText")
    frame.Show()
    app.MainLoop()

Zone de saisie utilisateur

Pour récupérer des entrées texte, on utilise wx.TextCtrl :

import wx

class FenetreSaisie(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        panel = wx.Panel(self)
        self.champ_saisie = wx.TextCtrl(panel, value="Entrez votre texte", pos=(20, 20), size=(250, -1))

if __name__ == "__main__":
    app = wx.App(False)
    frame = FenetreSaisie(None, title="Zone de saisie")
    frame.Show()
    app.MainLoop()

Ajout de boutons interactifs

Les boutons déclenchent des actions via des gestionnaires d'événements :

import wx

class FenetreAvecBouton(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        panel = wx.Panel(self)
        bouton = wx.Button(panel, label="Action", pos=(30, 30))
        
        bouton.Bind(wx.EVT_BUTTON, self.quand_clique)
    
    def quand_clique(self, evenement):
        print("Le bouton a été activé")

if __name__ == "__main__":
    app = wx.App(False)
    frame = FenetreAvecBouton(None, title="Gestion des événements")
    frame.Show()
    app.MainLoop()

Organisation avec BoxSizer

Le BoxSizer permet une disposition flexible des composants :

import wx

class FenetreAvecMiseEnPage(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        panel = wx.Panel(self)
        disposition = wx.BoxSizer(wx.VERTICAL)
        
        titre = wx.StaticText(panel, label="Interface organisée")
        disposition.Add(titre, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 10)
        
        champ = wx.TextCtrl(panel, value="Saisie ici")
        disposition.Add(champ, 0, wx.ALL | wx.EXPAND, 10)
        
        action_btn = wx.Button(panel, label="Valider")
        action_btn.Bind(wx.EVT_BUTTON, lambda e: print(f"Valeur: {champ.GetValue()}"))
        disposition.Add(action_btn, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 10)
        
        panel.SetSizer(disposition)

if __name__ == "__main__":
    app = wx.App(False)
    frame = FenetreAvecMiseEnPage(None, title="Layout avec Sizer")
    frame.Show()
    app.MainLoop()

Gestion des événements

La programmation événementielle constitue le paradigme fondamental des GUI. Les interactions utilisateur déclenchent des événements qui sont traités par des fonctions spécifiques, créant ainsi une application réactive et interactive.

La méthode Bind établit la connexion entre un événement (comme un clic) et sa fonction de traitement, permettant une réaction appropriée aux actions de l'utilisateur.

Publié le 9 août à 17h07