Interface graphique
Module Tkinter
Plusieurs modules existe pour la créations d'interfaces graphiques. Parmis ceux-ci, Tkinter est inclus dans toutes les versions de Python et n'a donc pas besoin d'installation séparée.
Si vous avez IPython (normalement inclus dans l'installation de Jupyter du cours dernier), il est possible de voir l'interface créée à fur et mesure, ligne par ligne. Sinon, il faut attendre la dernière ligne avant de voir le tout se matérialiser.
Un exemple:
In [1]: import Tkinter as tk
In [2]: racine = tk.Tk()
In [3]: etiquette = tk.Label(racine, text='Bonjour')
In [4]: etiquette.pack()
In [5]: bouton = tk.Button(racine, text='Quitter', command = racine.destroy)
In [6]: bouton.pack()
In [7]: racine.mainloop()
Tkinter inclut les composantes à partir duquel vous pouvez construire votre interface, chacun représenté par une classe. Il est conseillé de lire les ressources sur la page du TP plutôt que le help de ces classes.
Ces morceaux d'interface sont appellés « widgets ».
Button: Button qui exécute un fonction lorsqu'on appui dessus.
Checkbutton: Case à cocher.
Entry: Champs d'entrée texte.
Menu: Un menu déroulant ou bien un menu pop up
Label: Étiquette contenant du texte (ou une image).
Radiobutton: Permet de choisir une valeur parmi plusieurs possibilités.
Tk: « Racine » de l'application graphique. C'est aussi la première fenêtre.
Toplevel: Une autre fenêtre qui n'est pas la « racine ».
Canvas: Un espace pour disposer divers éléments dessinés (lignes, cercles, rectangles, etc).
Menubutton: Un bouton-menu, à utiliser pour les menus déroulants.
Listbox: Une liste de choix proposés à l’utilisateur.
Scrollbar: Barre de défilement
Text: Affichage de texte formatté. Permet aussi à l’utilisateur d’éditer le texte affiché.
Emplacement
Maintenant que nous avons vu quelques widgets de base, il faut spécifier où ils sont placé les uns par rapport aux autres.
L'emplacement voulue des widgets peut être décrite de trois façons différentes:
- En utilisant Frame, qui est un contenant de d’autres widgets. Il suffit d'emboîter les
Frame s et passer les bons paramètres à la méthode pack pour obtenir l'organisation voulue.
- Utiliser la méthode
place à la place de pack pour placer un élément à un endroit exacte.
grid permet de disposer par coordonnées l'emplacement des widgets dans une grille.
Exemple Frame et pack
import Tkinter as tk
racine = tk.Tk()
premier = tk.Label(racine, text='premier')
premier.pack(side='top')
deuxieme = tk.Label(racine, text='deuxième')
deuxieme.pack(side='top')
troisieme = tk.Frame(racine)
troisieme.pack(side='top')
gauche = tk.Label(troisieme, text='gauche')
gauche.pack(side='left')
milieu = tk.Label(troisieme, text='milieu')
milieu.pack(side='left')
droite = tk.Label(troisieme, text='droite')
droite.pack(side='left')
racine.mainloop()
Remarque: Le premier paramètre donné lors de la création d'un widget est le widget qui devrait contenir celui-ci.
Les valeurs possible pour side= sont 'top', 'left', 'right', 'bottom'. Ici, les widgets contenus dans un Frame (ou Tk ou Toplevel ) sont distribués uniformément. Pour voir les autres options possibles, lire le help(tk.Label.pack) ou les documents de référence.
Remarque (avancé): D'avoir mis pack comme méthode du widget contenu (plutôt que le widget contenant) est atypique de Python et est un vestige du langage Tcl/Tk. Le module Tkinter de Python est une interface vers les fonctions de ce langage.
Exemple place
Si on ajoute ces deux lignes avant la fin du mainloop dans l'exemple précédent, on verrait le nouveau Label ajouté par dessus le reste.
flottant = tk.Label(racine, text='flottant')
flottant.place(x=10, y=20)
Ici, nous appelons la méthode place à la place de pack .
Exemple grid
Nous pouvons aussi appeller la méthode grid à la place de pack .
import Tkinter as tk
racine = tk.Tk()
premier = tk.Label(racine, text='premier')
premier.grid(row=1, column=1)
deuxieme = tk.Label(racine, text='deuxième')
deuxieme.grid(row=3, column=2)
troisieme = tk.Label(racine, text='trosième')
troisieme.grid(row=2, column=3)
racine.mainloop()
Il est déconseiller d'utiliser grid et pack ensemble dans un même contenant (Frame, Tk ou Toplevel).
Actions de l'utilisateur
Pour exécuter une fonction lorsque l'utilisateur appuie sur la touche Entrée sur un widget Entry, nous pouvons utiliser la
import Tkinter as tk
def touche_entree(widget):
# Affiche le contenu entré
print entry.get()
racine = tk.Tk()
entry = tk.Entry(racine)
entry.pack()
entry.bind('<Return>', touche_entree)
racine.mainloop()
bind
bind peut aussi associer une fonction aux clicks et movements de la souris, etc. Voici une liste des possibilité obtenue d'ici
<KeyPress> |
Pression sur n'importe quelle touche |
<KeyPress-a> |
Pression sur la touche ‘A’ (minuscule) |
<KeyPress-A> |
Pression sur la touche ‘A’ (majuscule) |
<Return> |
Pression sur entrée |
<Escape> |
Touche d’échappement |
<Up> <Down> |
Pression sur les flèches |
<Button-1> |
Click souris gauche |
<Button-2> |
Click souris milieu (ou gauche et droite) |
<Button-3> |
Click souris droit |
<ButtonRelease> |
Fin de click gauche |
<Motion> |
Mouvement de la souris |
<B1-Motion> |
Mouvement de la souris avec click gauche |
<Enter> <Leave> |
Entrée et sortie souris d’un widget |
<Configure> |
Redimensionnement de la fenêtre |
<Map> <Unmap> |
Ouverture et iconification de la fenêtre |
Idée du fonctionnement en général
Lorsqu'une action est prise par l'utilisateur, l'idée est de récupérer la valeur des états et selon l'action, engendrer l'effet voulue.
Cette méthode de fonctionnement, où l'on réagit à des actions par des appels à des fonctions porte le nom de programmation évènementielle.
Question (avancée): Comment est-ce que la programmation évènementielle est possible? Nous savons que les programmes sont pourtant exécutés ligne par ligne.
Références
Pour une liste plus exhaustive des fonctions de Tkinter et des paramètres que l'on peut leur passer.
|