Tutoriel Tkinter OptionMenu
Apprenez à créer des listes déroulantes avec Tkinter OptionMenu : callbacks, mises à jour en direct, ajout/suppression d'options, conseils de style et un exemple complet exécutable.
Progression du tutoriel
1 Introduction à Tkinter OptionMenu
OptionMenu dans Tkinter crée une liste déroulante liée à une variable. Il est utile pour des choix tels que les thèmes, les langues ou tout ensemble fini d'options. Sous le capot, il stocke la valeur sélectionnée dans une variable et peut appeler une fonction chaque fois que l'utilisateur sélectionne un nouvel élément.
À la fin de ce guide, vous aurez une application de sélection de thèmes exécutable qui met à jour un volet de prévisualisation et affiche un message avec le thème sélectionné.
2 Prérequis : Python et Tkinter
Vous aurez besoin de Python 3.7+. Tkinter est inclus avec la plupart des installations Python sur macOS et Windows. Si vous êtes sous Linux, installez le package tk :
# Debian/Ubuntu
sudo apt-get install python3-tk
Vérifiez que Tkinter est disponible :
python -m tkinter
Si une petite fenêtre s'ouvre, Tkinter fonctionne.
3 OptionMenu minimal : les éléments essentiels
Vous avez besoin de trois éléments : une variable Tkinter (généralement StringVar), une liste d'options et un OptionMenu connecté à la variable.
import tkinter as tk
root = tk.Tk()
root.title("OptionMenu minimal")
# 1) Variable pour stocker la sélection actuelle
choice = tk.StringVar(value="A")
# 2) Créer l'OptionMenu, en passant la variable et les options
menu = tk.OptionMenu(root, choice, "A", "B", "C")
menu.pack(padx=20, pady=20)
root.mainloop()
- StringVar maintient la valeur actuelle synchronisée avec la liste déroulante.
value="A"définit la valeur par défaut ; sans cela, la première option est généralement sélectionnée.- Mettre à jour
choice.set("B")déplacera la sélection de l'OptionMenu par programmation.
4 Réagir aux changements : ajouter un rappel
Passez une fonction à l'argument command. Tkinter l'appellera avec la nouvelle valeur sélectionnée.
import tkinter as tk
from tkinter import messagebox
def on_select(value):
messagebox.showinfo("Sélection", f"Vous avez choisi : {value}")
root = tk.Tk()
choice = tk.StringVar(value="Océan")
menu = tk.OptionMenu(root, choice, "Océan", "Forêt", "Coucher de soleil", command=on_select)
menu.pack(padx=20, pady=20)
root.mainloop()
Utilisez les rappels pour synchroniser d'autres widgets, déclencher une validation ou mettre à jour un panneau d'informations.
5 Construire une prévisualisation en direct (comme notre exemple)
Stockez les données du thème, puis mettez à jour un volet de prévisualisation à chaque changement de sélection.
import tkinter as tk
from tkinter import messagebox
themes = {
"Océan": {"primary": "#1a73e8", "secondary": "#4285f4", "text": "white"},
"Forêt": {"primary": "#2e7d32", "secondary": "#4caf50", "text": "white"},
"Coucher de soleil": {"primary": "#d32f2f", "secondary": "#f44336", "text": "white"},
}
def update_preview(theme_name):
t = themes[theme_name]
preview.configure(bg=t["primary"])
title.configure(bg=t["primary"], fg=t["text"])
button.configure(bg=t["secondary"], fg=t["text"], activebackground=t["primary"], activeforeground=t["text"])
root = tk.Tk()
choice = tk.StringVar(value="Océan")
menu = tk.OptionMenu(root, choice, *themes.keys(), command=lambda v: update_preview(v))
menu.pack(padx=20, pady=10)
preview = tk.Frame(root, width=220, height=120, relief="raised", bd=2)
preview.pack(pady=10)
title = tk.Label(preview, text="Aperçu du thème")
title.pack(pady=6)
button = tk.Button(preview, text="OK", command=lambda: messagebox.showinfo("Thème", f"{choice.get()}"))
button.pack(pady=6)
update_preview(choice.get())
root.mainloop()
6 Modifier les options et désactiver les éléments
OptionMenu n'expose pas d'API intégrée pour ajouter/supprimer. L'approche habituelle consiste à reconstruire le menu avec les options mises à jour et à préserver la sélection actuelle.
def rebuild_options(new_options, keep_value=True):
current = choice.get() if keep_value else new_options[0]
menu["menu"].delete(0, "end")
for opt in new_options:
menu["menu"].add_command(label=opt, command=lambda v=opt: choice.set(v))
choice.set(current)
# Commencer avec ceci
choices = ["A", "B", "C"]
choice = tk.StringVar(value="B")
menu = tk.OptionMenu(root, choice, *choices)
menu.pack(padx=20, pady=20)
# Plus tard, supprimer "B"
rebuild_options([opt for opt in choices if opt != "B"])
Pour désactiver un élément spécifique, enveloppez-le dans un sous-menu cascade et utilisez state="disabled". Supprimer ou réordonner est plus simple avec une reconstruction.
7 Style et mise en page : maîtriser le look
Utilisez configure(width=...) pour contrôler la largeur. Pour les polices et les couleurs, définissez les attributs sur le menu et son widget de menu interne. La combinaison de ttk.Frame avec tk.OptionMenu peut améliorer l'espacement.
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
frame = ttk.Frame(root, padding=16)
frame.pack()
choice = tk.StringVar(value="Océan")
menu = tk.OptionMenu(frame, choice, "Océan", "Forêt", "Coucher de soleil")
menu.configure(width=14, font=("Helvetica", 11))
menu["menu"].configure(font=("Helvetica", 11))
ttk.Label(frame, text="Choisissez un thème :").pack(anchor="w", pady=(0, 6))
menu.pack(anchor="w")
root.mainloop()
8 Pièges courants et problèmes
- Oublier de définir une valeur initiale peut entraîner une sélection vide.
- Les rappels reçoivent la nouvelle valeur, pas la variable. Utilisez la variable si vous avez besoin d'un état plus large.
- OptionMenu n'a pas d'API directe pour « supprimer une option » — reconstruisez via le widget interne
menu. - Mélanger
tketttkpeut produire de subtiles différences de style. - Sur certains systèmes, changer les polices du menu interne n'a aucun effet en raison du rendu de la plateforme.
9 Exercice : ajouter et supprimer des options
Étendez l'exemple minimal : ajoutez un champ de saisie et un bouton qui insère l'option tapée dans le menu (si elle n'est pas déjà présente) et la sélectionne. Ajoutez ensuite un autre bouton pour supprimer l'option actuellement sélectionnée.
import tkinter as tk
root = tk.Tk()
choice = tk.StringVar(value="A")
options = ["A", "B", "C"]
menu = tk.OptionMenu(root, choice, *options)
menu.pack(padx=16, pady=16)
entry = tk.Entry(root)
entry.pack(padx=16)
def add_option():
val = entry.get().strip()
if not val or val in options:
return
options.append(val)
menu["menu"].add_command(label=val, command=lambda v=val: choice.set(val))
choice.set(val)
def remove_selected():
val = choice.get()
if val not in options:
return
options.remove(val)
rebuild_options()
tk.Button(root, text="Ajouter", command=add_option).pack(pady=6)
tk.Button(root, text="Supprimer la sélection", command=remove_selected).pack(pady=6)
def rebuild_options():
current = choice.get()
menu["menu"].delete(0, "end")
for opt in options:
menu["menu"].add_command(label=opt, command=lambda v=opt: choice.set(v))
if options:
choice.set(current if current in options else options[0])
root.mainloop()
10 Projet complet : Sélecteur de thème avec prévisualisation
Copiez ceci dans un fichier nommé theme_selector.py et exécutez-le avec python theme_selector.py.
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
class ColorThemeSelector(tk.Tk):
def __init__(self):
super().__init__()
# Configuration de la fenêtre principale
self.title("Exemple OptionMenu")
self.geometry("400x300")
self.configure(padx=20, pady=20)
# Définir les thèmes de couleur
self.color_themes = {
"Océan": {"primary": "#1a73e8", "secondary": "#4285f4", "text": "white"},
"Forêt": {"primary": "#2e7d32", "secondary": "#4caf50", "text": "white"},
"Coucher de soleil": {"primary": "#d32f2f", "secondary": "#f44336", "text": "white"},
"Lavande": {"primary": "#7b1fa2", "secondary": "#9c27b0", "text": "white"}
}
# Créer et configurer un cadre
self.main_frame = ttk.Frame(self)
self.main_frame.pack(expand=True, fill='both')
# Créer une StringVar pour stocker l'option sélectionnée
self.selected_theme = tk.StringVar()
self.selected_theme.set("Océan") # Définir la valeur par défaut
# Créer une étiquette
self.label = ttk.Label(
self.main_frame,
text="Sélectionnez votre thème de couleur :",
font=('Helvetica', 12)
)
self.label.pack(pady=10)
# Créer l'OptionMenu
self.theme_menu = tk.OptionMenu(
self.main_frame,
self.selected_theme,
*self.color_themes.keys(),
command=self.update_preview
)
self.theme_menu.configure(width=15)
self.theme_menu.pack(pady=10)
# Créer un cadre de prévisualisation
self.preview_frame = tk.Frame(
self.main_frame,
width=200,
height=100,
relief="raised",
bd=2
)
self.preview_frame.pack(pady=20)
# Créer des éléments de prévisualisation
self.preview_title = tk.Label(
self.preview_frame,
text="Aperçu du thème",
font=('Helvetica', 10)
)
self.preview_title.pack(pady=5)
self.preview_button = tk.Button(
self.preview_frame,
text="Bouton d'exemple",
command=self.show_selection
)
self.preview_button.pack(pady=10)
# Initialiser la prévisualisation
self.update_preview()
def update_preview(self, *args):
"""Mettre à jour le cadre de prévisualisation avec les couleurs du thème sélectionné"""
theme = self.color_themes[self.selected_theme.get()]
# Mettre à jour l'arrière-plan du cadre de prévisualisation
self.preview_frame.configure(bg=theme["primary"])
self.preview_title.configure(
bg=theme["primary"],
fg=theme["text"]
)
self.preview_button.configure(
bg=theme["secondary"],
fg=theme["text"],
activebackground=theme["primary"],
activeforeground=theme["text"]
)
def show_selection(self):
"""Afficher une boîte de message avec la sélection actuelle"""
messagebox.showinfo(
"Thème sélectionné",
f"Vous avez sélectionné le thème {self.selected_theme.get()} !"
)
if __name__ == "__main__":
app = ColorThemeSelector()
app.mainloop()
Exécutez-le : python theme_selector.py. Essayez de changer de thème — regardez la prévisualisation se mettre à jour en temps réel.