logo oujood
🔍

Gérer le clic d'un bouton Tkinter

Le clic est l'événement le plus courant dans une interface Tkinter. Voici comment le gérer proprement, avec ou sans arguments, et éviter les pièges classiques.

OUJOOD.COM

Le paramètre command du widget Button est la façon la plus directe de réagir à un clic. Mais selon la complexité de l'action à déclencher, plusieurs schémas s'offrent à vous — et certains pièges valent la peine d'être connus avant de les tomber dessus.

Rappel : command sans parenthèses

La règle fondamentale : on passe la référence à la fonction, sans l'appeler :

📋 Copier le code

import tkinter as tk

def action():
    label.config(text="Bouton cliqué !")

fenetre = tk.Tk()
fenetre.geometry("300x130")

# Correct : référence à la fonction
tk.Button(fenetre, text="Cliquer", command=action).pack(pady=20)

# Incorrect : appel immédiat au moment de la création
# tk.Button(fenetre, text="Cliquer", command=action()).pack()

label = tk.Label(fenetre, text="En attente...")
label.pack()

fenetre.mainloop()

L'erreur avec les parenthèses est particulièrement traîtresse parce qu'elle ne génère pas de message d'erreur — la fonction s'exécute simplement au mauvais moment, et command reçoit None (la valeur de retour de la fonction).

Passer des arguments au clic

Quand la fonction à appeler attend des paramètres, deux approches fonctionnent : lambda pour les cas simples, functools.partial pour les cas où lambda dans une boucle pose problème :

📋 Copier le code

import tkinter as tk
from functools import partial

def afficher_couleur(couleur, label_affichage):
    label_affichage.config(text=f"Couleur choisie : {couleur}", bg=couleur)

fenetre = tk.Tk()
fenetre.geometry("360x180")

label_result = tk.Label(fenetre, text="Choisissez une couleur", width=30, height=2)
label_result.pack(pady=15)

frame_btns = tk.Frame(fenetre)
frame_btns.pack()

couleurs = [("Rouge", "#ef9a9a"), ("Vert", "#a5d6a7"), ("Bleu", "#90caf9")]

for nom, hex_val in couleurs:
    # partial évite le piège de la closure dans une boucle
    cmd = partial(afficher_couleur, hex_val, label_result)
    tk.Button(frame_btns, text=nom, bg=hex_val, command=cmd).pack(side="left", padx=5)

fenetre.mainloop()

Le piège de lambda dans une boucle est classique : si on écrit command=lambda: afficher_couleur(hex_val, label_result), tous les boutons capturent la dernière valeur de hex_val après la fin de la boucle. partial ou lambda c=hex_val: afficher_couleur(c, label_result) fixent la valeur au moment de la création.

Bouton toggle — changer d'état au clic

Un bouton qui bascule entre deux états est un cas fréquent — pause/lecture, activer/désactiver :

📋 Copier le code

import tkinter as tk

fenetre = tk.Tk()
fenetre.geometry("300x150")

actif = tk.BooleanVar(value=False)

def basculer():
    actif.set(not actif.get())
    if actif.get():
        btn.config(text="⏸ Pause", bg="#ef5350", activebackground="#c62828")
        label_etat.config(text="État : en cours")
    else:
        btn.config(text="▶ Démarrer", bg="#66bb6a", activebackground="#388e3c")
        label_etat.config(text="État : arrêté")

btn = tk.Button(fenetre, text="▶ Démarrer", command=basculer,
                bg="#66bb6a", fg="white", font=("Arial", 12),
                activebackground="#388e3c", activeforeground="white",
                relief="flat", padx=20, pady=6)
btn.pack(pady=25)

label_etat = tk.Label(fenetre, text="État : arrêté", font=("Arial", 10), fg="#555")
label_etat.pack()

fenetre.mainloop()

On stocke l'état dans une BooleanVar plutôt qu'une variable globale — c'est plus propre et on peut observer les changements avec trace_add() si nécessaire.

Pour les événements plus fins — clic droit, double-clic, survol — la méthode bind() prend le relais. Et si vous avez plusieurs boutons qui partagent une logique commune, les fonctions callback structurées proprement évitent la duplication de code.

Par carabde | Mis à jour le 30 avril 2025