Python : Tkinter

De www.yakakliker.org

Passer de la console à une interface graphique (GUI) est une étape passionnante. En Python, l'outil standard inclus par défaut s'appelle Tkinter.

Contrairement à un script classique qui s'exécute de haut en bas, une interface graphique fonctionne avec une boucle d'événements (event loop) : le programme "attend" que l'utilisateur clique sur un bouton ou tape du texte.

Les concepts de base de Tkinter

Pour créer une fenêtre, nous manipulons des Widgets (composants graphiques) :

  • Tk : La fenêtre principale.
  • Label : Un texte affiché.
  • Entry : Un champ de saisie de texte.
  • Button : Un bouton cliquable.
  • Listbox : Une zone pour afficher notre liste d'invités.

Exemple

import tkinter as tk

def dire_bonjour():
    nom = entree.get() # On récupère le texte de la saisie
    label_resultat.config(text=f"Bonjour {nom} !")

# 1. Création de la fenêtre
fenetre = tk.Tk()
fenetre.title("Mon Premier Programme")
fenetre.geometry("300x200")

# 2. Ajout des composants
label_instruction = tk.Label(fenetre, text="Entrez votre nom :")
label_instruction.pack(pady=10)

entree = tk.Entry(fenetre)
entree.pack()

bouton = tk.Button(fenetre, text="Valider", command=dire_bonjour)
bouton.pack(pady=10)

label_resultat = tk.Label(fenetre, text="")
label_resultat.pack()

# 3. Lancement de la boucle principale
fenetre.mainloop()

Analyse factuelle du fonctionnement

  • .pack() : C'est un gestionnaire de géométrie. Il place les éléments les uns en dessous des autres.
  • command=dire_bonjour : On lie le bouton à une fonction. Notez qu'on ne met pas de parenthèses () à la fonction ici, car on veut que le bouton l'appelle plus tard, au moment du clic.
  • .mainloop() : Cette ligne est cruciale. Elle empêche la fenêtre de se fermer immédiatement et permet à Python d'écouter les clics de souris.

Ajout d'un bouton "Quitter" à l'interface

import tkinter as tk

def dire_bonjour():
    nom = entree.get()
    if nom.strip():
        label_resultat.config(text=f"Bonjour {nom} !", fg="blue")
    else:
        label_resultat.config(text="Veuillez entrer un nom", fg="red")

# 1. Création de la fenêtre
fenetre = tk.Tk()
fenetre.title("Mon Premier Programme")
fenetre.geometry("300x250")

# 2. Ajout des composants
label_instruction = tk.Label(fenetre, text="Entrez votre nom :")
label_instruction.pack(pady=10)

entree = tk.Entry(fenetre)
entree.pack()

bouton = tk.Button(fenetre, text="Valider", command=dire_bonjour)
bouton.pack(pady=10)

label_resultat = tk.Label(fenetre, text="")
label_resultat.pack()

# --- AJOUT DU BOUTON QUITTER ---
# On utilise directement fenetre.destroy comme commande
bouton_quitter = tk.Button(fenetre, text="Quitter", command=fenetre.destroy, fg="white", bg="red")
bouton_quitter.pack(pady=20)


# 3. Lancement de la boucle principale
fenetre.mainloop()

Analyse des ajouts

  • command=fenetre.destroy : Cette méthode ordonne à Tkinter de fermer la fenêtre et d'arrêter la boucle mainloop. C'est la manière propre de fermer une application.
  • fg et bg : Ce sont les abréviations de Foreground (couleur du texte) et Background (couleur de fond). Cela vous permet de personnaliser l'apparence de vos boutons.
  • La logique de placement : Le bouton "Quitter" apparaît en dernier car il est le dernier à être "packé" (.pack()).

Exemple plus complet

import tkinter as tk
from tkinter import messagebox
import json

# --- LOGIQUE DE DONNÉES ---
FICHIER = "mes_invites.json"

def charger_donnees():
    try:
        with open(FICHIER, "r", encoding="utf-8") as f:
            return json.load(f)
    except FileNotFoundError:
        return []

def sauvegarder_donnees(liste):
    with open(FICHIER, "w", encoding="utf-8") as f:
        json.dump(liste, f, indent=4, ensure_ascii=False)

# --- ACTIONS DE L'INTERFACE ---
def rafraichir_liste():
    """Efface et réaffiche la liste dans le widget Listbox."""
    liste_visuelle.delete(0, tk.END)
    for inv in invites:
        liste_visuelle.insert(tk.END, f"{inv['nom']} - {inv['age']} ans")

def ajouter_action():
    nom = entree_nom.get().strip()
    age_str = entree_age.get().strip()
    
    if nom and age_str.isdigit():
        invites.append({"nom": nom, "age": int(age_str)})
        sauvegarder_donnees(invites)
        rafraichir_liste()
        # Effacer les champs après ajout
        entree_nom.delete(0, tk.END)
        entree_age.delete(0, tk.END)
    else:
        messagebox.showwarning("Erreur", "Veuillez entrer un nom et un âge valide.")

def supprimer_action():
    selection = liste_visuelle.curselection()
    if selection:
        index = selection[0]
        invites.pop(index)
        sauvegarder_donnees(invites)
        rafraichir_liste()
    else:
        messagebox.showinfo("Info", "Sélectionnez un nom dans la liste pour le supprimer.")

# --- CONSTRUCTION DE LA FENÊTRE ---
invites = charger_donnees()
fenetre = tk.Tk()
fenetre.title("Gestionnaire d'Invités")
fenetre.geometry("400x500")

# Widgets de saisie
tk.Label(fenetre, text="Nom :").pack(pady=5)
entree_nom = tk.Entry(fenetre)
entree_nom.pack()

tk.Label(fenetre, text="Âge :").pack(pady=5)
entree_age = tk.Entry(fenetre)
entree_age.pack()

# Boutons d'action
tk.Button(fenetre, text="Ajouter l'invité", command=ajouter_action, bg="lightgreen").pack(pady=10)
tk.Button(fenetre, text="Supprimer la sélection", command=supprimer_action, bg="salmon").pack(pady=5)

# Affichage de la liste
tk.Label(fenetre, text="Liste des inscrits :").pack(pady=10)
liste_visuelle = tk.Listbox(fenetre, width=40)
liste_visuelle.pack(pady=5)

# Initialisation de l'affichage
rafraichir_liste()

fenetre.mainloop()

Analyse des éléments techniques

  • messagebox : C'est un sous-module de Tkinter qui permet de faire apparaître de petites fenêtres d'alerte ou d'erreur (très pratique pour guider l'utilisateur).
  • Listbox : C'est le widget qui affiche une liste d'éléments sélectionnables. On utilise .insert() pour ajouter et .delete() pour vider.
  • curselection() : Cette méthode permet de savoir quelle ligne l'utilisateur a cliqué dans la liste (elle renvoie un index, ex: 0 pour le premier).
  • invites.pop(index) : C'est l'équivalent de .remove(), mais on supprime par la position (index) plutôt que par la valeur.