OUJOOD.COM
Un script Tkinter sans classes fonctionne bien pour 10-15 widgets. Au-delà, les variables globales s'accumulent, les fonctions callback deviennent difficiles à tester, et ajouter une nouvelle fonctionnalité nécessite de toucher à tout. L'organisation en classes résout ces problèmes sans compliquer le code — elle le structure.
Pattern de base — hériter de tk.Frame
Le pattern le plus courant consiste à créer une classe qui hérite de tk.Frame. L'interface est construite dans __init__, les callbacks deviennent des méthodes :
import tkinter as tk
class CompteurApp(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.pack(fill="both", expand=True)
self.compteur = 0
self._creer_widgets()
def _creer_widgets(self):
self.label = tk.Label(
self, text="0",
font=("Arial", 48, "bold"),
fg="#1565c0"
)
self.label.pack(pady=30)
frame_btn = tk.Frame(self)
frame_btn.pack()
tk.Button(frame_btn, text="−", width=4, font=("Arial", 14),
command=self.decrementer).pack(side="left", padx=8)
tk.Button(frame_btn, text="+", width=4, font=("Arial", 14),
command=self.incrementer).pack(side="left", padx=8)
tk.Button(frame_btn, text="Reset", width=6,
command=self.reinitialiser).pack(side="left", padx=8)
def incrementer(self):
self.compteur += 1
self._mettre_a_jour()
def decrementer(self):
self.compteur -= 1
self._mettre_a_jour()
def reinitialiser(self):
self.compteur = 0
self._mettre_a_jour()
def _mettre_a_jour(self):
self.label.config(text=str(self.compteur))
couleur = "#2e7d32" if self.compteur > 0 else "#c62828" if self.compteur < 0 else "#1565c0"
self.label.config(fg=couleur)
if __name__ == "__main__":
fenetre = tk.Tk()
fenetre.title("Compteur")
fenetre.geometry("320x200")
CompteurApp(fenetre)
fenetre.mainloop()
Les widgets sont des attributs de l'instance (self.label) — accessibles depuis toutes les méthodes sans variables globales. Les méthodes préfixées par _ sont conventionnellement privées : _creer_widgets() et _mettre_a_jour() sont des détails d'implémentation, pas des points d'entrée publics.
Hériter de tk.Tk — l'application principale
Pour la fenêtre principale elle-même, on peut hériter directement de tk.Tk :
import tkinter as tk
from tkinter import messagebox
class Application(tk.Tk):
def __init__(self):
super().__init__()
self.title("Application structurée")
self.geometry("420x300")
self.resizable(False, False)
self.protocol("WM_DELETE_WINDOW", self.quitter)
self._donnees = []
self._creer_interface()
def _creer_interface(self):
# Zone de saisie
frame_top = tk.Frame(self, bg="#f5f5f5")
frame_top.pack(fill="x", padx=15, pady=10)
tk.Label(frame_top, text="Ajouter :", bg="#f5f5f5").pack(side="left")
self.champ = tk.Entry(frame_top, width=22)
self.champ.pack(side="left", padx=8)
self.champ.bind("", lambda e: self.ajouter())
tk.Button(frame_top, text="Ajouter", command=self.ajouter).pack(side="left")
# Liste
self.liste = tk.Listbox(self, height=8, font=("Arial", 11))
self.liste.pack(fill="both", expand=True, padx=15)
tk.Button(self, text="Supprimer la sélection",
command=self.supprimer).pack(pady=8)
def ajouter(self):
valeur = self.champ.get().strip()
if valeur:
self._donnees.append(valeur)
self.liste.insert(tk.END, valeur)
self.champ.delete(0, tk.END)
def supprimer(self):
indices = self.liste.curselection()
for i in reversed(indices):
self.liste.delete(i)
del self._donnees[i]
def quitter(self):
if messagebox.askokcancel("Quitter", "Fermer l'application ?"):
self.destroy()
if __name__ == "__main__":
app = Application()
app.mainloop()
Hériter de tk.Tk donne accès direct aux méthodes de la fenêtre (self.title(), self.protocol()) sans passer par une référence externe. Les données sont stockées dans self._donnees — accessibles depuis toutes les méthodes, sans aucune variable globale.
Pour des applications plus grandes avec plusieurs écrans ou onglets, la page sur l'organisation des fichiers montre comment répartir ces classes dans des modules séparés. Les callbacks décrits précédemment deviennent naturellement des méthodes dans ce contexte.
Par carabde | Mis à jour le 30 avril 2025