Un champ de texte qui accepte plusieurs lignes, permet la mise en forme et peut même servir de mini éditeur de code ne demande que quelques lignes de Python. Le widget Text de Tkinter, souvent désigné par l’expression tkinter text dans les exemples anglophones, offre justement cette souplesse. Voici comment le créer, lire son contenu, le styliser, lui ajouter une barre de défilement et éviter les erreurs les plus courantes.
Les points essentiels pour exploiter Text efficacement
- Multiligne : Text convient aux notes, journaux, éditeurs et zones de commentaire.
-
Index précis :
1.0désigne la première ligne et le premier caractère. -
Méthodes indispensables :
insert(),get()etdelete()couvrent les opérations de base. - Mise en forme : les tags permettent d’appliquer plusieurs styles dans une même zone.
-
Bonne pratique : utilisez
end-1cpour récupérer le texte sans le saut de ligne final ajouté par Tkinter.
Comprendre le widget Text de Tkinter
Text est une zone d’édition capable d’afficher et de modifier du texte sur plusieurs lignes. Contrairement à Label, il accepte la saisie utilisateur, et contrairement à Entry, il convient aux contenus longs comme une note, un message ou un fichier source.
Je le choisis dès qu’un utilisateur doit écrire plus d’une ligne. Pour une adresse e-mail ou un nom, Entry reste plus simple. Pour une description, un commentaire ou un éditeur, Text est nettement plus adapté.
| Widget | Usage principal | Particularité |
|---|---|---|
Label |
Afficher une information | Non modifiable |
Entry |
Saisir une courte valeur | Une seule ligne |
Text |
Rédiger ou afficher un contenu long | Multiligne et personnalisable |
Son système d’index mérite une attention particulière. 1.0 représente le début de la première ligne, tandis que 2.5 pointe vers le sixième caractère de la deuxième ligne. Les lignes commencent à 1, mais les caractères commencent à 0.
Créer une zone Text fonctionnelle
La version minimale tient en quelques instructions. L’option wrap contrôle le retour à la ligne automatique, tandis que height et width indiquent une taille approximative en lignes et en caractères.
import tkinter as tk
fenetre = tk.Tk()
fenetre.title("Éditeur Tkinter")
fenetre.geometry("650x400")
zone = tk.Text(
fenetre,
height=15,
width=70,
wrap="word",
font=("Arial", 12),
padx=10,
pady=10
)
zone.pack(fill="both", expand=True)
zone.insert("1.0", "Écrivez votre texte ici...")
fenetre.mainloop()
J’utilise généralement fill="both" et expand=True pour que la zone profite de l’espace disponible. Sans ces options, elle reste souvent figée dans un coin de la fenêtre, ce qui donne une interface peu agréable dès que la fenêtre est redimensionnée.
Les options qui changent vraiment l’expérience
-
wrap="word"coupe les lignes entre les mots. -
wrap="char"autorise une coupure caractère par caractère. -
wrap="none"conserve les longues lignes et nécessite souvent un défilement horizontal. -
undo=Trueactive l’historique annuler-rétablir. -
state="disabled"transforme la zone en affichage non modifiable. -
font,bgetfgpermettent d’adapter rapidement son apparence.
Pour une interface destinée à la lecture, je préfère state="disabled" plutôt qu’un widget totalement différent. Il conserve les fonctions de sélection et de copie, tout en empêchant les modifications accidentelles.
Insérer, lire et supprimer du contenu
Trois méthodes suffisent pour les opérations courantes. insert() ajoute du texte, get() le récupère et delete() le supprime. La combinaison la plus utilisée est zone.get("1.0", "end-1c"), car elle évite de récupérer le saut de ligne final automatique de Tkinter.
import tkinter as tk
fenetre = tk.Tk()
zone = tk.Text(fenetre, width=60, height=12)
zone.pack(padx=12, pady=12)
def ajouter_texte():
zone.insert("end", "\nNouvelle ligne ajoutée.")
def afficher_texte():
contenu = zone.get("1.0", "end-1c")
print(contenu)
def vider_zone():
zone.delete("1.0", "end")
tk.Button(fenetre, text="Ajouter", command=ajouter_texte).pack()
tk.Button(fenetre, text="Afficher", command=afficher_texte).pack()
tk.Button(fenetre, text="Vider", command=vider_zone).pack()
fenetre.mainloop()
La position "end" signifie la fin logique du contenu, mais elle inclut le caractère de nouvelle ligne placé par le widget. Pour une sauvegarde ou une comparaison de chaînes, end-1c est presque toujours le choix correct.
Travailler avec la sélection
La sélection courante se trouve entre les index sel.first et sel.last. Comme aucune sélection n’existe parfois, il faut intercepter l’exception tk.TclError au lieu de supposer que ces index sont toujours disponibles.
def copier_selection():
try:
texte = zone.get("sel.first", "sel.last")
fenetre.clipboard_clear()
fenetre.clipboard_append(texte)
except tk.TclError:
print("Aucun texte sélectionné.")
Cette approche est pratique pour construire une barre d’outils, mais les raccourcis clavier natifs de Tkinter couvrent déjà une partie des besoins. Je réserve donc les boutons Copier, Couper ou Rechercher aux applications où ces fonctions doivent être visibles.
Mettre en forme du texte avec les tags
Un tag est un nom associé à une portion de texte. Il peut modifier la couleur, la police ou l’arrière-plan sans changer le contenu lui-même. C’est ce mécanisme qui permet de mélanger du texte normal, des avertissements et des titres dans une seule zone.
import tkinter as tk
fenetre = tk.Tk()
zone = tk.Text(fenetre, width=70, height=12)
zone.pack(padx=12, pady=12)
zone.tag_configure(
"titre",
font=("Arial", 14, "bold"),
foreground="#174a7e"
)
zone.tag_configure(
"alerte",
foreground="#a00020",
background="#ffe5e5"
)
zone.insert("1.0", "Journal de l’application\n", "titre")
zone.insert("end", "Connexion établie.\n")
zone.insert("end", "Attention : fichier introuvable.", "alerte")
fenetre.mainloop()
On peut aussi appliquer un tag après l’insertion avec tag_add(). Cette méthode est utile pour un surligneur, un moteur de recherche ou une coloration syntaxique simple.
zone.tag_add("alerte", "3.0", "3.end")
Rechercher une occurrence
La méthode search() renvoie l’index de la prochaine occurrence trouvée. Le code suivant parcourt le contenu et met en évidence chaque apparition du mot recherché.
def surligner_mot(mot):
zone.tag_remove("alerte", "1.0", "end")
debut = "1.0"
while True:
position = zone.search(mot, debut, stopindex="end-1c", nocase=True)
if not position:
break
fin = f"{position}+{len(mot)}c"
zone.tag_add("alerte", position, fin)
debut = fin
Le tag ne remplace pas une véritable coloration syntaxique pour un langage complexe, mais il suffit pour un journal d’événements, un outil de recherche ou un éditeur de configuration léger. Pour un gros fichier source, je déconseille de rescanner tout le contenu à chaque frappe, car l’interface peut perdre en fluidité.
Ajouter une barre de défilement et des raccourcis
Une zone Text devient rapidement inconfortable sans défilement. Le branchement doit être fait dans les deux sens, avec yscrollcommand du côté de Text et command du côté de la barre.
import tkinter as tk
fenetre = tk.Tk()
fenetre.geometry("700x450")
cadre = tk.Frame(fenetre)
cadre.pack(fill="both", expand=True)
zone = tk.Text(cadre, wrap="word", undo=True)
barre = tk.Scrollbar(cadre, orient="vertical", command=zone.yview)
zone.configure(yscrollcommand=barre.set)
zone.pack(side="left", fill="both", expand=True)
barre.pack(side="right", fill="y")
fenetre.mainloop()
Pour aller plus vite, le module tkinter.scrolledtext fournit une variante déjà équipée d’une barre verticale. Elle réduit le code, mais offre moins de contrôle sur la disposition si l’interface devient plus élaborée.
from tkinter.scrolledtext import ScrolledText
zone = ScrolledText(fenetre, wrap="word", undo=True)
zone.pack(fill="both", expand=True)
Les événements personnalisés sont utiles pour les fonctions métier. Par exemple, peut déclencher une sauvegarde, tandis que peut ouvrir une recherche. Une fonction liée à un événement reçoit toujours un objet événement.
def sauvegarder_raccourci(event=None):
contenu = zone.get("1.0", "end-1c")
with open("notes.txt", "w", encoding="utf-8") as fichier:
fichier.write(contenu)
fenetre.bind("", sauvegarder_raccourci)
Sauvegarder le contenu sans piège
Le widget ne sauvegarde rien automatiquement. Il faut extraire la chaîne, choisir un encodage et gérer les erreurs d’accès au fichier. Pour du texte français, utf-8 doit être le choix par défaut, car il conserve correctement les accents et les caractères spéciaux.
import tkinter as tk
from tkinter import filedialog, messagebox
def enregistrer():
chemin = filedialog.asksaveasfilename(
defaultextension=".txt",
filetypes=[("Fichiers texte", "*.txt"), ("Tous les fichiers", "*.*")]
)
if not chemin:
return
try:
contenu = zone.get("1.0", "end-1c")
with open(chemin, "w", encoding="utf-8") as fichier:
fichier.write(contenu)
except OSError as erreur:
messagebox.showerror("Erreur", f"Impossible d'enregistrer le fichier : {erreur}")
Dans une application réelle, j’ajoute aussi un indicateur de modification non enregistrée. Le point important est de ne pas confondre le contenu affiché avec le fichier sur le disque. Tant que l’utilisateur n’a pas lancé l’enregistrement, ces deux états peuvent être différents.
Éviter les erreurs les plus fréquentes
Utiliser le mauvais widget
Text ne remplace pas toujours Entry. Si le programme attend une valeur courte, une seule ligne et une validation immédiate, Entry sera plus simple à exploiter. Choisir Text uniquement parce qu’il est plus grand ajoute souvent une gestion inutile des index et des retours à la ligne.
Oublier que les index sont spécifiques
Un index comme 2.4 n’est pas un index Python classique. Il représente une position dans la structure interne de Tkinter. Les expressions telles que "insert", "end-1c", "sel.first" ou "2.end" sont souvent plus lisibles que des calculs manuels.
Lire aussi : Exécuter un script Python - La méthode robuste et sans erreur
Modifier une zone désactivée
Avec state="disabled", les appels à insert() et delete() sont bloqués. Pour mettre à jour le contenu, il faut temporairement réactiver le widget, effectuer la modification, puis le désactiver à nouveau.
zone.configure(state="normal")
zone.delete("1.0", "end")
zone.insert("1.0", "Contenu actualisé")
zone.configure(state="disabled")
Enfin, évitez de créer un nouveau widget à chaque clic pour afficher des résultats. Réutiliser la même zone, la vider puis la remplir est plus léger et conserve mieux la sélection, le défilement et la logique de l’interface.
Une base solide pour vos interfaces Python
Pour commencer, retenez ce trio simple. Créez un widget Text avec une disposition extensible, utilisez insert(), get() et delete() pour le contenu, puis ajoutez les tags et le défilement seulement lorsque l’application en a réellement besoin.
La vraie force de ce composant ne vient pas de sa taille, mais de sa combinaison entre édition multiligne, index précis, recherche et mise en forme. Pour un bloc-notes, un afficheur de logs ou un petit éditeur Python, cette base reste simple, fiable et suffisamment flexible pour évoluer sans réécrire toute l’interface.