Une fenêtre Tkinter peut vite devenir difficile à maintenir dès que les champs, boutons et messages doivent rester alignés lorsque l’utilisateur redimensionne l’interface. Le gestionnaire tkinter grid répond précisément à ce besoin en organisant les widgets dans des lignes et des colonnes. Je vais montrer comment le mettre en place, le rendre responsive, gérer les espacements et éviter les erreurs qui produisent des interfaces déséquilibrées.
Les principes essentiels pour construire une interface Tkinter équilibrée
- grid() place les widgets dans des cellules organisées par lignes et colonnes.
- sticky="nsew" permet à un widget de s’étirer dans sa cellule.
- weight=1 indique quelles lignes et colonnes absorbent l’espace supplémentaire.
- rowspan et columnspan permettent de fusionner plusieurs cellules.
- Il ne faut pas mélanger pack() et grid() dans un même conteneur.
Comprendre le gestionnaire tkinter grid
La méthode grid() place chaque widget dans une cellule définie par une ligne et une colonne. Les indices commencent à zéro, ce qui signifie que la première cellule correspond à row=0 et column=0.
import tkinter as tk
fenetre = tk.Tk()
fenetre.title("Formulaire")
tk.Label(fenetre, text="Nom").grid(row=0, column=0)
tk.Entry(fenetre).grid(row=0, column=1)
tk.Label(fenetre, text="E-mail").grid(row=1, column=0)
tk.Entry(fenetre).grid(row=1, column=1)
fenetre.mainloop()
Ce fonctionnement est particulièrement adapté aux formulaires, aux tableaux de paramètres et aux fenêtres de configuration. Contrairement à pack(), qui empile les widgets autour des bords, la grille donne un contrôle direct sur leur position relative.
Je recommande de réserver chaque grille à un conteneur clair, souvent une instance de Frame. Cette organisation évite les mises en page difficiles à modifier lorsque l’application grandit.
Les options qui comptent vraiment
| Option | Rôle | Exemple |
|---|---|---|
row |
Définit la ligne du widget | row=0 |
column |
Définit la colonne du widget | column=1 |
padx et pady
|
Ajoutent un espace extérieur | padx=8 |
ipadx et ipady
|
Ajoutent un espace intérieur | ipady=4 |
rowspan et columnspan
|
Étendent un widget sur plusieurs cellules | columnspan=2 |
Faire réagir la fenêtre avec sticky et weight
Une grille correctement positionnée peut tout de même sembler figée si ses colonnes ne savent pas utiliser l’espace disponible. Deux réglages font presque toute la différence : sticky contrôle l’alignement du widget, tandis que weight détermine comment l’espace supplémentaire est distribué.
Les lettres de sticky correspondent aux directions cardinales. Ainsi, "w" aligne le widget à gauche, "e" à droite et "nsew" l’étire dans les quatre directions.
import tkinter as tk
fenetre = tk.Tk()
fenetre.geometry("500x220")
fenetre.columnconfigure(1, weight=1)
fenetre.rowconfigure(1, weight=1)
tk.Label(fenetre, text="Adresse").grid(
row=0, column=0, padx=10, pady=10, sticky="w"
)
champ = tk.Entry(fenetre)
champ.grid(row=0, column=1, padx=10, pady=10, sticky="ew")
zone = tk.Text(fenetre)
zone.grid(row=1, column=0, columnspan=2, padx=10, pady=10, sticky="nsew")
fenetre.mainloop()
La colonne 1 reçoit ici un poids de 1 et peut donc s’élargir. La ligne 1 fonctionne de la même manière pour la zone de texte. Sans ces deux instructions, la fenêtre pourrait s’agrandir, mais les widgets resteraient concentrés dans leur taille minimale, ce qui donne souvent une impression de vide.
Un poids de 2 reçoit environ deux fois plus d’espace supplémentaire qu’un poids de 1. Pour deux colonnes de largeur équivalente, attribuez-leur le même poids, par exemple weight=1 sur chacune.
Construire un formulaire propre avec Frame
Pour une interface réaliste, je préfère séparer la fenêtre en zones fonctionnelles. Un Frame peut contenir le formulaire, un autre les boutons d’action et un troisième un message d’état. Chaque conteneur possède alors sa propre grille, ce qui rend le code plus lisible.
import tkinter as tk
from tkinter import ttk
fenetre = tk.Tk()
fenetre.title("Création de compte")
fenetre.geometry("420x230")
formulaire = ttk.Frame(fenetre, padding=16)
formulaire.grid(row=0, column=0, sticky="nsew")
fenetre.columnconfigure(0, weight=1)
fenetre.rowconfigure(0, weight=1)
formulaire.columnconfigure(1, weight=1)
ttk.Label(formulaire, text="Nom").grid(
row=0, column=0, padx=6, pady=6, sticky="w"
)
ttk.Entry(formulaire).grid(
row=0, column=1, padx=6, pady=6, sticky="ew"
)
ttk.Label(formulaire, text="Mot de passe").grid(
row=1, column=0, padx=6, pady=6, sticky="w"
)
ttk.Entry(formulaire, show="*").grid(
row=1, column=1, padx=6, pady=6, sticky="ew"
)
boutons = ttk.Frame(formulaire)
boutons.grid(row=2, column=0, columnspan=2, pady=(14, 0))
ttk.Button(boutons, text="Annuler").grid(row=0, column=0, padx=4)
ttk.Button(boutons, text="Valider").grid(row=0, column=1, padx=4)
fenetre.mainloop()
Le point important est que le poids doit être configuré dans le parent qui gère la grille. Dans cet exemple, c’est formulaire qui doit rendre la colonne 1 extensible, et non le champ Entry lui-même.
Les espaces extérieurs avec padx et pady améliorent souvent davantage le résultat que l’ajout de couleurs ou de bordures. Je conseille de commencer avec une valeur comprise entre 6 et 16 pixels, puis d’ajuster selon la densité de l’interface.
Fusionner des cellules et aligner plusieurs widgets
Les options columnspan et rowspan servent lorsqu’un élément doit occuper plusieurs cellules. Un titre peut ainsi traverser toute la largeur d’un formulaire, tandis qu’une grande zone de texte peut prendre plusieurs lignes.
titre = ttk.Label(
formulaire,
text="Informations personnelles",
font=("Arial", 14, "bold")
)
titre.grid(row=0, column=0, columnspan=2, pady=(0, 12))
ttk.Label(formulaire, text="Prénom").grid(
row=1, column=0, sticky="w"
)
ttk.Entry(formulaire).grid(
row=1, column=1, sticky="ew"
)
Pour des colonnes qui doivent conserver la même largeur malgré des contenus différents, la configuration uniform peut être utile. Elle est moins fréquente dans les petits scripts, mais elle devient intéressante pour des panneaux de boutons ou des tableaux de commandes réguliers.
Un autre détail souvent négligé concerne l’alignement des étiquettes. Utiliser sticky="w" pour les textes placés à gauche donne une ligne visuelle nette. Sans cette option, les labels peuvent sembler centrés dans leurs cellules et rendre le formulaire moins naturel.
Éviter les erreurs classiques avec grid
Ne pas mélanger pack et grid dans le même parent
Tkinter permet d’utiliser pack(), grid() et place(), mais un même conteneur ne doit pas être géré simultanément par pack et grid. Cette erreur déclenche généralement un message TclError et bloque l’affichage.
cadre = ttk.Frame(fenetre)
cadre.grid(row=0, column=0)
# Correct
ttk.Label(cadre, text="Nom").grid(row=0, column=0)
ttk.Entry(cadre).grid(row=0, column=1)
Le mélange reste possible dans des conteneurs différents. Par exemple, la fenêtre principale peut utiliser pack() pour empiler plusieurs cadres, tandis que chaque cadre utilise sa propre grille interne. C’est même une stratégie pratique pour les interfaces complexes.
Vérifier le parent réel du widget
Un widget doit être placé dans la grille de son parent direct. Si un champ appartient à formulaire, configurez les lignes et colonnes de formulaire, pas celles de la fenêtre principale. Cette confusion explique une grande partie des layouts qui refusent de s’étirer.
Lire aussi : Python str.replace - Maîtrisez le remplacement de sous-chaînes
Utiliser les outils de diagnostic
Quand un widget disparaît ou se retrouve au mauvais endroit, inspectez sa position avec grid_info(). Les méthodes grid_size(), grid_slaves() et grid_forget() sont également utiles pour comprendre la structure en cours d’exécution.
print(champ.grid_info())
print(formulaire.grid_size())
print(formulaire.grid_slaves())
Je vérifie aussi les dimensions de la fenêtre avant de modifier le code. Un widget mal visible n’est pas toujours mal positionné : il peut simplement être trop petit, masqué par un autre élément ou placé dans une ligne sans poids.
Choisir entre grid, pack et place
Le choix du gestionnaire dépend surtout de la structure souhaitée. Pour une décision rapide, cette comparaison suffit dans la plupart des projets Python.
| Gestionnaire | Usage recommandé | Limite principale |
|---|---|---|
grid |
Formulaires, tableaux, interfaces redimensionnables | Demande une configuration des lignes et colonnes |
pack |
Empilement simple de cadres ou de boutons | Moins précis pour les alignements en deux dimensions |
place |
Positionnement fixe ou effets très spécifiques | Résiste mal aux changements de taille et de police |
Pour une fenêtre composée de champs alignés, je choisis presque toujours grid. Pour une barre horizontale de boutons, pack() peut être plus rapide. Quant à place(), je le réserve aux cas où la position en pixels est réellement voulue, car il devient fragile dès que l’interface doit s’adapter.
La méthode la plus fiable pour une grille responsive
Une mise en page solide suit généralement quatre règles simples. Je les applique dès le début, car corriger une grille devenue complexe coûte beaucoup plus de temps que la préparer correctement.
- Créer un Frame par zone fonctionnelle.
- Configurer
weight=1sur les lignes et colonnes qui doivent grandir. - Utiliser
sticky="ew"pour les champs horizontaux etsticky="nsew"pour les zones extensibles. - Conserver des espacements réguliers avec
padxetpady.
Testez ensuite la fenêtre avec trois tailles différentes, par exemple 300, 500 et 800 pixels de largeur. Si les champs restent lisibles, que les boutons ne se chevauchent pas et que l’espace est réparti de manière logique, la base est saine.
La grille ne remplace pas une réflexion sur l’ergonomie. Elle fournit un système précis pour distribuer l’espace, mais c’est la hiérarchie des informations, la taille des textes et la cohérence des marges qui donnent à l’application son confort d’utilisation.
Ce que votre grille Tkinter doit réussir avant la mise en production
Une bonne interface ne se contente pas d’afficher les widgets au bon endroit. Elle doit rester compréhensible lorsque la fenêtre change de taille, lorsqu’un texte devient plus long ou lorsqu’un champ reçoit une valeur inattendue.
Commencez avec une structure simple, utilisez des cadres pour isoler les responsabilités et vérifiez systématiquement les couples weight et sticky. Cette combinaison résout la majorité des problèmes de redimensionnement rencontrés avec Tkinter.
Si une grille devient trop difficile à lire, ce n’est généralement pas un signe qu’il faut abandonner Tkinter. C’est souvent le moment de découper l’interface en plusieurs Frame indépendants, chacun avec une mise en page courte, prévisible et facile à tester.