Blog ENI : Toute la veille numérique !
💥 Un livre PAPIER acheté
= La version EN LIGNE offerte pendant 1 an !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici

Créer une application graphique en 20 minutes

Objectif

1. Fonctionnel

L’objectif de l’application à construire ici est de créer une application qui accède aux mêmes données que celles accédées par l’application web et l’application console en passant par le même modèle et la même configuration.

L’interface graphique proposée est similaire à l’interface web, mais elle offre une expérience utilisateur différente étant donné que les créations d’une interface web et d’une interface graphique ne répondent pas aux mêmes exigences et aux mêmes règles.

2. Technique

L’enjeu principal d’une application graphique réussie est de permettre un dialogue efficace entre les actions de l’utilisateur qui clique sur les éléments graphiques ou saisit des données et la manipulation effective et persistante de ces données.

La conception d’une interface graphique consiste à créer des éléments graphiques tels que des zones de texte d’information, des zones de saisie de données plus ou moins similaires à celles que l’on peut croiser en HTML. La différence est que le lien entre le formulaire et l’application se fait via des callbacks et non des requêtes.

La librairie TkInter fait partie du cœur de Python, elle n’est donc pas une bibliothèque externe qu’il faudrait rajouter. Elle a été remaniée pour Python 3 (https://docs.python.org/3/howto/pyporting.html) et y est donc portée. C’est une excellente bibliothèque, mais ce n’est pas celle que nous allons utiliser ici.

Nous allons en effet préférer l’utilisation d’une bibliothèque plus complète, qui a fait peau neuve et dont on va faire une très courte...

Présentation rapide de Gtk et d’astuces

1. Présentation

Gtk est une bibliothèque graphique associée à l’environnement graphique Gnome. Elle est issue du projet Gimp : ses créateurs ont trouvé qu’il serait dommage d’avoir créé autant de composants et de ne pas offrir l’opportunité à d’autres de réutiliser leur formidable travail pour créer d’autres applications.

PyGTK est une bibliothèque graphique libre connectant GTK+ à Python 2. Pour Python 3, il s’agit de gi.repository. Cette dernière est écrite en C (elle utilise Cairo) et est partie intégrante d’un ensemble beaucoup plus vaste. Elle est utilisée par de nombreux logiciels de référence comme Gimp par exemple qui en est à l’origine et par les environnements de bureau Gnome et Xfce. Elle est liée à la Libglade et à un logiciel de création d’interfaces graphiques Glade qui est pratique et efficace.

La bibliothèque GTK+ a été l’objet de changements en profondeur permettant la sortie de GTK3+ (nécessitant des cassures de rétrocompatibilité parfaitement compréhensibles) et sous Python 3 on dispose uniquement de cette nouvelle branche.

Il est important de noter l’existence d’une documentation de référence indispensable qui permet de démarrer progressivement, pas à pas, et que je vous conseille de suivre avant ou après avoir lu ce chapitre :  http://readthedocs.org/docs/python-gtk-3-tutorial/en/latest/index.html

En effet, l’exemple présenté ici est volontairement complémentaire de cette documentation, présentant d’autres aspects.

Les deux points importants abordés ici sont la séparation des différents...

Démarrer le programme

Comme vu précédemment, il faut créer un nouveau point d’entrée pour démarrer notre programme, et ceci se fait dans le fichier pyproject.toml :

[tool.poetry.plugins."console_scripts"] 
initialize_project_db = "project.scripts.initialize_db:main" 
show_settings = "project.scripts.settings:main" contact = "project.scripts.contact:main" 
gcontact = contact.scripts.gtk:main 

Pour garder la compatibilité avec l’ancien système, on peut également modifier le fichier setup.py :

setup(name='contact', 
      version='0.0', 
      description='contact', 
      [...], 
      install_requires=requires, 
      entry_points="""\ 
      [paste.app_factory] 
      main = contact:main 
      [console_scripts] 
      initialize_contact_db = contact.scripts.initializedb:main 
      show_settings = contact.scripts.settings:main 
      contact = contact.scripts.contact:main 
      gcontact = contact.scripts.gtk:main 
      """, 
      ) 

Il faut maintenant redéployer l’application :

$ poetry build 
$ poetry add ./project 

Il faut ensuite créer un fichier gtk.py dans le répertoire scripts et on peut commencer à rajouter ce code :

#!/usr/bin/python3 
 
import argparse 
 
from pyramid.paster import bootstrap 
from sqlalchemy...

Interface graphique avec Glade

Quitte à travailler avec GTK, l’adoption d’un outil puissant comme Glade est un vrai gain de temps. D’autant que le résultat produit peut aussi bien être utilisé avec Python qu’en C.

Pour cet exemple, il a été dessiné une fenêtre, nommée main_window, laquelle contient une grille de deux colonnes et de quatre lignes. Les trois premières lignes de la première colonne sont remplies par des labels.

Vous pourrez noter que le nom donné à chacun de ces composants est important et peut être modifié.

Dans la seconde colonne, on ajoute successivement un simple champs (Entry), une liste de sélection (ComboBox), une zone de texte (TextView) et enfin une boîte contenant deux cases que l’on positionnera de manière horizontale pour y rajouter deux boutons.

images/RI403I01.png

Interface générale de Glade et événements sur la fenêtre

Comme vous pouvez le constater, l’interface n’est pas forcément agréable à l’œil nu. Mais ce qui compte, ce sont les paramètres que vous trouverez dans les divers onglets du panneau en bas à droite.

Vous pourrez choisir le fait que les différents éléments de la grille aient la même longueur ou non, le fait qu’ils soient centrés, alignés en haut à droite…

Plus important, vous pourrez sélectionner les callbacks à rattacher à des événements particuliers. Sur la fenêtre principale, l’événement important est le clic sur la croix permettant de quitter l’application.

Ici, on le rattache à la méthode nommée on_main_window_destroy.

Les deux autres éléments à positionner rapidement sont les deux boutons. On va relier le bouton d’annulation...

Créer le composant graphique

Le composant graphique va disposer de trois méthodes : une méthode d’initialisation et les deux méthodes de callback, c’est-à-dire la méthode pour quitter l’application lorsque l’on clique sur la croix ou sur le bouton d’annulation, et la méthode de validation qui va créer un contact.

Voici cette classe, les explications sont insérées pour chaque étape :

class GtkContact: 
    def __init__(self, controller): 
        self.controller = controller 

On commence par agréger le contrôleur à l’instance courante, ce qui permettra d’accéder aux méthodes utiles permettant de récupérer les sujets ou de créer le contact. Ensuite, il faut charger l’interface que l’on vient de dessiner avec Glade :

        interface = Gtk.Builder() 
        interface.add_from_file('contact/templates/contact.glade') 

On se contente de créer le builder et de charger le fichier Glade. Ensuite, il faut récupérer des pointeurs vers les champs utiles, ce que l’on peut faire parce qu’on les a correctement nommés dans Glade :

    # Lien vers les champs utiles         
        self.email = interface.get_object("email_entry") 
        self.subject = interface.get_object("subject_id_combobox") 
        self.text = interface.get_object("message_textview") 

Maintenant, on peut s’attaquer au remplissage de la liste de sélection. Cela se fait en plusieurs étapes....

Contrôleur

L’interface a pour but de permettre la saisie d’un contact. Elle doit également fournir la liste des sujets, de manière à peupler une liste déroulante. Ce sont les deux seules actions que l’on attend de la part du contrôleur. C’est aussi lui qui va générer l’interface graphique et également lancer la boucle événementielle.

Voici ce contrôleur :

class Controller: 
    def __init__(self, DBSession): 
        self.DBSession = DBSession 
        GtkContact(self) 
        Gtk.main() 
 
    def get_subjects(self): 
        return DBSession.query(Subject).all() 
 
    def add_contact(self, email, subject_id, text): 
        with transaction.manager: 
            DBSession.add(Contact(email=email, subject_id=subject_id, 
text=text)) 

C’est lors de l’appel de Gtk.main que le programme se met en pause et à l’écoute des événements générés par l’utilisateur. Ce n’est que lorsque l’on quitte l’application par un appel à Gtk.main_quit que cette boucle se termine.

Voici le résultat :

images/RI403I05.png

Application graphique avec le log de SQLAlchemy en arrière-plan

Autres bibliothèques graphiques

1. TkInter

TkInter est la bibliothèque graphique utilisée par Python et elle est un portage de la bibliothèque graphique de Tk créée pour le langage TLC.

Elle présente le grand avantage d’être très simple à mettre en œuvre et ressemble beaucoup à Gtk dans l’approche générale.

2. wxPython

La bibliothèque wxPython est une bibliothèque connectant wxWidgets à Python. Elle est une alternative à TkInter très prisée car particulièrement complète, proche du système d’exploitation.

La bibliothèque wxWidgets est une bibliothèque graphique libre écrite en C++ qui permet d’écrire une interface graphique qui sera identique quel que soit le système d’exploitation mais en prenant son apparence.

Cette bibliothèque est une référence, et fonctionne sous Python 3 à partir de la version 3.3.

3. PyQt

PyQt est une bibliothèque graphique libre connectant Qt à Python. Qt, qui doit se prononcer comme le mot anglais « cute », est écrit en C++ et est très portable. L’environnement graphique KDE repose sur Qt. De nombreux modules complémentaires additionnels en font plus qu’une simple bibliothèque permettant de réaliser des interfaces graphiques.

Qt est associée à QtDesigner qui est, à l’instar de Glade, un logiciel de création d’interfaces graphiques.

Qt est intégralement porté sur Python 3.x depuis sa version 4.5, ce qui en fait un excellent candidat. Il est également mature et assez stable dans ses évolutions.

4. PySide

PySide est une nouvelle implémentation de Qt pour Python. La différence principale est la licence plus permissive (LGPL...