Comment créer et contrôler des animations avec Tkinter

Tkinter fait partie de la bibliothèque standard de Python et est largement utilisé pour créer des applications GUI. Cet article explique en détail comment créer des animations avec Tkinter et comment les contrôler. Nous aborderons la création d’animations de base, l’implémentation d’animations avancées avec des images clés, ainsi que la manière de contrôler la lecture, l’arrêt et la réinitialisation des animations à travers des exemples de code. Ce guide est utile pour un large éventail de lecteurs, des débutants aux utilisateurs intermédiaires.

Qu’est-ce que Tkinter ?

Tkinter est une bibliothèque standard de Python qui permet de créer des interfaces graphiques (GUI). Elle combine une syntaxe simple avec des fonctionnalités puissantes et est idéale pour construire des applications de bureau en utilisant des widgets (boutons, étiquettes, zones de texte, etc.). En utilisant Tkinter, vous pouvez ajouter des éléments visuels à vos programmes Python et enrichir l’interaction avec l’utilisateur. La flexibilité et la facilité d’utilisation de Tkinter en font un excellent choix pour créer des animations.

Comment créer une animation simple

Nous allons décrire les étapes de base pour créer une animation simple avec Tkinter. Dans l’exemple suivant, un cercle se déplace sur l’écran.

Étape 1 : Installation et importation de Tkinter

Commencez par importer Tkinter. Étant une bibliothèque standard de Python, il n’y a pas besoin d’installation supplémentaire.

import tkinter as tk

Étape 2 : Création de la fenêtre

Ensuite, créez une fenêtre dans laquelle l’animation sera affichée.

root = tk.Tk()
root.title("Animation simple")
canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()

Étape 3 : Création de l’objet à animer

Créez un objet à animer (dans cet exemple, un cercle) dans le widget Canvas.

ball = canvas.create_oval(10, 10, 50, 50, fill='blue')

Étape 4 : Logique de l’animation

Ensuite, implémentez la logique de l’animation. Définissez la fonction move_ball qui met à jour la position du cercle.

def move_ball():
    canvas.move(ball, 2, 0)  # Déplace le cercle vers la droite
    canvas.after(50, move_ball)  # Appelle à nouveau cette fonction après 50 millisecondes

Étape 5 : Démarrer l’animation

Enfin, commencez l’animation.

move_ball()
root.mainloop()

En combinant ces étapes, vous pouvez créer une animation simple avec Tkinter. Dans cet exemple, un cercle bleu se déplace continuellement vers la droite.

Implémentation d’animations avec des images clés

Pour créer des animations plus complexes, il est essentiel de comprendre et d’implémenter le concept des images clés. Une image clé représente un moment clé dans une animation, et l’interpolation entre ces images permet de créer des mouvements fluides.

Étape 1 : Définir les images clés

Commencez par définir des images clés pour différentes positions et états dans l’animation. Par exemple, créons une animation où un cercle se déplace à l’écran tout en changeant de taille.

keyframes = [
    {'time': 0, 'x': 10, 'y': 10, 'size': 40},
    {'time': 1000, 'x': 200, 'y': 200, 'size': 80},
    {'time': 2000, 'x': 10, 'y': 300, 'size': 40},
]

Étape 2 : Interpolation entre les images clés

Définissez une fonction qui effectue l’interpolation entre les images clés en fonction du temps actuel. Cela permet d’obtenir des transitions fluides dans l’animation.

import time

def interpolate(start, end, progress):
    return start + (end - start) * progress

def get_current_frame():
    current_time = time.time() * 1000  # Conversion en millisecondes
    total_duration = keyframes[-1]['time']
    current_time = current_time % total_duration  # Boucle de l'animation

    for i, frame in enumerate(keyframes[:-1]):
        next_frame = keyframes[i + 1]
        if frame['time'] <= current_time < next_frame['time']:
            progress = (current_time - frame['time']) / (next_frame['time'] - frame['time'])
            x = interpolate(frame['x'], next_frame['x'], progress)
            y = interpolate(frame['y'], next_frame['y'], progress)
            size = interpolate(frame['size'], next_frame['size'], progress)
            return x, y, size

Étape 3 : Mise à jour de l’animation

Créez une fonction qui met à jour les coordonnées et la taille de l’objet dans le widget Canvas en fonction des images clés.

def update_animation():
    x, y, size = get_current_frame()
    canvas.coords(ball, x, y, x + size, y + size)
    canvas.after(50, update_animation)

Étape 4 : Démarrer l’animation

Utilisez la fonction de mise à jour pour démarrer l’animation.

update_animation()
root.mainloop()

Ce code crée une animation où le cercle se déplace à l’écran et change de taille selon les images clés. L’interpolation entre les images clés permet des transitions fluides, ce qui rend l’animation plus dynamique.

Contrôle des animations

Nous allons maintenant explorer comment contrôler une animation créée avec Tkinter (par exemple, pour la lire, la mettre en pause ou la réinitialiser). Le contrôle des animations est important pour rendre les interfaces utilisateur plus interactives.

Étape 1 : Ajouter des boutons de contrôle

Tout d’abord, nous allons ajouter des boutons pour contrôler l’animation. L’exemple suivant montre comment ajouter trois boutons : « Lecture », « Pause » et « Réinitialisation ».

play_button = tk.Button(root, text="Lecture", command=play_animation)
play_button.pack(side=tk.LEFT)

pause_button = tk.Button(root, text="Pause", command=pause_animation)
pause_button.pack(side=tk.LEFT)

reset_button = tk.Button(root, text="Réinitialiser", command=reset_animation)
reset_button.pack(side=tk.LEFT)

Étape 2 : Lire l’animation

Définissez la fonction play_animation pour démarrer ou reprendre l’animation.

is_paused = False

def play_animation():
    global is_paused
    is_paused = False
    update_animation()

Étape 3 : Mettre en pause l’animation

Définissez la fonction pause_animation pour mettre l’animation en pause.

def pause_animation():
    global is_paused
    is_paused = True

Étape 4 : Réinitialiser l’animation

Définissez la fonction reset_animation pour réinitialiser l’animation à sa position de départ.

def reset_animation():
    global is_paused
    is_paused = True
    canvas.coords(ball, 10, 10, 50, 50)  # Remettre à la position initiale

Étape 5 : Améliorer la fonction de mise à jour de l’animation

Modifiez la fonction update_animation pour qu’elle n’actualise l’animation que lorsque celle-ci n’est pas en pause.

def update_animation():
    if not is_paused:
        x, y, size = get_current_frame()
        canvas.coords(ball, x, y, x + size, y + size)
        canvas.after(50, update_animation)

En combinant ces étapes, vous pouvez désormais lire, mettre en pause et réinitialiser une animation créée avec Tkinter. Cela permet aux utilisateurs de contrôler l’animation et de créer des applications plus interactives.

Interaction avec l’interface utilisateur

Associer les animations à l’interface utilisateur permet d’améliorer l’ergonomie et l’attractivité des applications. Voyons comment intégrer les animations dans une interface utilisateur avec les widgets Tkinter.

Étape 1 : Ajouter un curseur

Ajoutons un curseur pour ajuster la vitesse ou la position de l’animation. Dans l’exemple suivant, nous créons un curseur pour ajuster la vitesse.

speed_slider = tk.Scale(root, from_=1, to=100, orient=tk.HORIZONTAL, label="Vitesse")
speed_slider.pack()

Étape 2 : Récupérer la valeur du curseur

Récupérez la valeur du curseur pour ajuster la vitesse de l’animation. Modifiez la fonction get_current_frame pour utiliser la valeur du curseur.

def get_current_frame():
    current_time = time.time() * 1000  # Conversion en millisecondes
    total_duration = keyframes[-1]['time']
    current_time = (current_time % total_duration) / speed_slider.get()  # Ajuste la vitesse avec la valeur du curseur

    for i, frame in enumerate(keyframes[:-1]):
        next_frame = keyframes[i + 1]
        if frame['time'] <= current_time < next_frame['time']:
            progress = (current_time - frame['time']) / (next_frame['time'] - frame['time'])
            x = interpolate(frame['x'], next_frame['x'], progress)
            y = interpolate(frame['y'], next_frame['y'], progress)
            size = interpolate(frame['size'], next_frame['size'], progress)
            return x, y, size

Étape 3 : Contrôler l’animation avec des boutons

En plus des boutons de contrôle, ajoutons la possibilité d’ajuster la vitesse de l’animation en temps réel à l’aide du curseur. Cela permet aux utilisateurs de modifier la vitesse de l’animation en temps réel.

def update_animation():
    if not is_paused:
        x, y, size = get_current_frame()
        canvas.coords(ball, x, y, x + size, y + size)
        canvas.after(50 // speed_slider.get(), update_animation)

play_button = tk.Button(root, text="Lecture", command=play_animation)
play_button.pack(side=tk.LEFT)

pause_button = tk.Button(root, text="Pause", command=pause_animation)
pause_button.pack(side=tk.LEFT)

reset_button = tk.Button(root, text="Réinitialiser", command=reset_animation)
reset_button.pack(side=tk.LEFT)

speed_slider = tk.Scale(root, from_=1, to=100, orient=tk.HORIZONTAL, label="Vitesse")
speed_slider.pack()

Étape 4 : Mise à jour de l’animation

Redéfinissez la fonction update_animation pour ajuster la vitesse de l’animation en fonction de la valeur du curseur.

def update_animation():
    if not is_paused:
        x, y, size = get_current_frame()
        canvas.coords(ball, x, y, x + size, y + size)
        canvas.after(50 // speed_slider.get(), update_animation)

Grâce à ce mécanisme, vous pouvez ajuster la vitesse de l’animation en temps réel à l’aide du curseur de l’interface utilisateur. Cela permet de rendre l’application plus interactive et intuitive pour l’utilisateur.

Exemple pratique : Mouvement d’un personnage

Dans cet exemple, nous allons créer une animation d’un personnage se déplaçant à l’écran. Nous allons utiliser une image de personnage et implémenter un mouvement plus complexe.

Étape 1 : Charger l’image du personnage

Nous allons charger une image de personnage à l’aide de PhotoImage de Tkinter.

character_image = tk.PhotoImage(file='character.png')
character = canvas.create_image(10, 10, anchor=tk.NW, image=character_image)

Étape 2 : Définir les images clés

Définissons les images clés pour déplacer le personnage à l’écran. Par exemple, nous allons créer une animation où le personnage se déplace en zigzag.

keyframes = [
    {'time': 0, 'x': 10, 'y': 10},
    {'time': 1000, 'x': 200, 'y': 10},
    {'time': 2000, 'x': 200, 'y': 200},
    {'time': 3000, 'x': 10, 'y': 200},
    {'time': 4000, 'x': 10, 'y': 10},
]

Étape 3 : Interpolation entre les images clés

Nous allons réutiliser la fonction d’interpolation pour déplacer le personnage entre les images clés.

def get_current_frame():
    current_time = time.time() * 1000  # Conversion en millisecondes
    total_duration = keyframes[-1]['time']
    current_time = (current_time % total_duration) / speed_slider.get()  # Ajuste la vitesse avec la valeur du curseur

    for i, frame in enumerate(keyframes[:-1]):
        next_frame = keyframes[i + 1]
        if frame['time'] <= current_time < next_frame['time']:
            progress = (current_time - frame['time']) / (next_frame['time'] - frame['time'])
            x = interpolate(frame['x'], next_frame['x'], progress)
            y = interpolate(frame['y'], next_frame['y'], progress)
            return x, y

Étape 4 : Améliorer la fonction de mise à jour de l’animation

Nous allons maintenant définir une fonction pour mettre à jour la position du personnage.

def update_animation():
    if not is_paused:
        x, y = get_current_frame()
        canvas.coords(character, x, y)
        canvas.after(50, update_animation)

Étape 5 : Démarrer l’animation

Appelez la fonction de mise à jour pour démarrer l’animation.

update_animation()
root.mainloop()

En combinant ces étapes, vous obtiendrez une animation où le personnage se déplace en zigzag sur l’écran. Les mouvements sont définis par les images clés, et la vitesse peut être ajustée à l’aide du curseur. Cela permet de créer des applications visuellement dynamiques et interactives.

Problèmes pratiques : Améliorer l’animation

Nous proposons ici des exercices pour améliorer l’animation que vous avez apprise. Ces exercices vous aideront à créer des animations plus complexes et à ajuster la vitesse ou les mouvements à l’aide des outils précédemment explorés.

Exercice 1 : Améliorer la boucle de l’animation

Rendez l’animation continue en configurant une boucle. Utilisez les images clés pour déplacer le personnage en cercle.

keyframes = [
    {'time': 0, 'x': 10, 'y': 10},
    {'time': 1000, 'x': 200, 'y': 10},
    {'time': 2000, 'x': 300, 'y': 100},
    {'time': 3000, 'x': 200, 'y': 200},
    {'time': 4000, 'x': 10, 'y': 200},
    {'time': 5000, 'x': 10, 'y': 100},
    {'time': 6000, 'x': 10, 'y': 10},
]

Exercice 2 : Modifier la couleur de l’animation avec un curseur

Ajoutez un curseur pour changer la couleur du personnage pendant l’animation. Utilisez ce curseur pour ajuster la couleur en fonction de sa valeur.

color_slider = tk.Scale(root, from_=0, to=255, orient=tk.HORIZONTAL, label="Couleur")
color_slider.pack()

def update_color():
    color_value = color_slider.get()
    color_hex = f'#{color_value:02x}{color_value:02x}{255-color_value:02x}'
    canvas.itemconfig(character, fill=color_hex)

Exercice 3 : Mouvement de plusieurs personnages

Créez une animation où plusieurs personnages se déplacent sur des trajectoires différentes. Définissez des images clés distinctes pour chaque personnage.

character2_image = tk.PhotoImage(file='character2.png')
character2 = canvas.create_image(300, 300, anchor=tk.NW, image=character2_image)

keyframes2 = [
    {'time': 0, 'x': 300, 'y': 300},
    {'time': 1000, 'x': 100, 'y': 300},
    {'time': 2000, 'x': 100, 'y': 100},
    {'time': 3000, 'x': 300, 'y': 100},
    {'time': 4000, 'x': 300, 'y': 300},
]

def get_current_frame2():
    current_time = time.time() * 1000
    total_duration = keyframes2[-1]['time']
    current_time = (current_time % total_duration) / speed_slider.get()

    for i, frame in enumerate(keyframes2[:-1]):
        next_frame = keyframes2[i + 1]
        if frame['time'] <= current_time < next_frame['time']:
            progress = (current_time - frame['time']) / (next_frame['time'] - frame['time'])
            x = interpolate(frame['x'], next_frame['x'], progress)
            y = interpolate(frame['y'], next_frame['y'], progress)
            return x, y

def update_animation2():
    if not is_paused:
        x, y = get_current_frame2()
        canvas.coords(character2, x, y)
        canvas.after(50, update_animation2)

update_animation2()

Ces exercices vous aideront à améliorer vos compétences en animation avec Tkinter en ajoutant de nouvelles fonctionnalités et en explorant de nouvelles idées.

Conclusion

Dans cet article, nous avons exploré en détail la création et le contrôle des animations avec Tkinter. Nous avons vu comment créer des animations simples, implémenter des animations complexes avec des images clés, et comment les intégrer dans des interfaces utilisateur interactives. Grâce à des exemples pratiques et des exercices, vous avez pu apprendre à personnaliser et améliorer vos animations.

En utilisant ces connaissances, vous pourrez créer des animations plus complexes et visuellement attrayantes, et améliorer vos compétences dans le développement d’applications GUI avec Tkinter. La prochaine étape consiste à apprendre à intégrer d’autres widgets et à gérer des événements pour créer des applications plus riches et interactives.