OUJOOD.COM
Le widget Progressbar appartient au module ttk et propose deux modes de fonctionnement : le mode déterminé, où la progression est connue et affichée sous forme de pourcentage, et le mode indéterminé, où la barre se déplace en boucle pour signaler qu'une tâche est en cours sans durée connue.
Mode déterminé
On fixe une valeur maximale et on incrémente la barre au fil de l'avancement :
import tkinter as tk
from tkinter import ttk
fenetre = tk.Tk()
fenetre.title("Progressbar déterminée")
fenetre.geometry("360x160")
valeur = tk.DoubleVar()
barre = ttk.Progressbar(
fenetre,
orient=tk.HORIZONTAL,
length=300,
mode="determinate",
variable=valeur,
maximum=100
)
barre.pack(pady=25)
label_pct = tk.Label(fenetre, text="0 %")
label_pct.pack()
etape = [0] # liste pour contourner la limitation des closures
def avancer():
if etape[0] < 100:
etape[0] += 10
valeur.set(etape[0])
label_pct.config(text=f"{etape[0]} %")
if etape[0] >= 100:
label_pct.config(text="Terminé !")
btn.config(state="disabled")
btn = tk.Button(fenetre, text="Avancer (+10%)", command=avancer)
btn.pack()
fenetre.mainloop()
On lie la barre à une DoubleVar via variable — quand la variable change, la barre se met à jour automatiquement. On peut aussi appeler directement barre["value"] = 50 ou barre.step(10) pour incrémenter de 10 unités.
Mode indéterminé
Quand la durée d'une tâche n'est pas connue, le mode indeterminate anime la barre en boucle :
import tkinter as tk
from tkinter import ttk
fenetre = tk.Tk()
fenetre.title("Progressbar indéterminée")
fenetre.geometry("340x160")
barre = ttk.Progressbar(
fenetre,
orient=tk.HORIZONTAL,
length=280,
mode="indeterminate"
)
barre.pack(pady=25)
label_etat = tk.Label(fenetre, text="En attente...")
label_etat.pack()
def demarrer():
barre.start(15) # intervalle en ms entre chaque pas
label_etat.config(text="Chargement en cours...")
btn_start.config(state="disabled")
btn_stop.config(state="normal")
def arreter():
barre.stop()
label_etat.config(text="Arrêté.")
btn_start.config(state="normal")
btn_stop.config(state="disabled")
frame = tk.Frame(fenetre)
frame.pack()
btn_start = tk.Button(frame, text="Démarrer", command=demarrer)
btn_start.pack(side="left", padx=8)
btn_stop = tk.Button(frame, text="Arrêter", command=arreter, state="disabled")
btn_stop.pack(side="left")
fenetre.mainloop()
start(interval) lance l'animation avec un pas toutes les interval millisecondes. stop() l'arrête et remet la barre à zéro. La valeur passée à start() contrôle la vitesse : un intervalle plus petit donne une animation plus rapide.
Progressbar avec after() — mise à jour depuis le thread principal
Tkinter n'est pas thread-safe — mettre à jour la barre depuis un thread secondaire provoque des comportements imprévisibles. La solution propre utilise after() pour programmer des mises à jour dans la boucle principale :
import tkinter as tk
from tkinter import ttk
fenetre = tk.Tk()
fenetre.title("Progressbar avec after()")
fenetre.geometry("340x150")
barre = ttk.Progressbar(fenetre, length=280, mode="determinate", maximum=100)
barre.pack(pady=20)
label = tk.Label(fenetre, text="Prêt")
label.pack()
def simuler_tache(progression=0):
if progression <= 100:
barre["value"] = progression
label.config(text=f"Traitement... {progression} %")
# planifie la prochaine mise à jour dans 80 ms
fenetre.after(80, simuler_tache, progression + 5)
else:
label.config(text="Terminé !")
tk.Button(fenetre, text="Lancer", command=lambda: simuler_tache(0)).pack()
fenetre.mainloop()
after(délai_ms, fonction, *args) planifie un appel dans la boucle d'événements principale après délai_ms millisecondes. La fenêtre reste réactive pendant toute la durée — l'utilisateur peut toujours interagir. Pour les vraies tâches longues en arrière-plan, la page sur after() et les threads couvre les cas plus avancés.
Par carabde | Mis à jour le 30 avril 2025