Guide to Widget Animations with Tkinter

Learn how to create cool animations to satisfy and fascinate your users

Introduction

Animations are an important feature in the application and game development sectors. They aren’t always necessary and aren’t crucial. You can create apps and games without them. But they add something unique: movement. There are very few games in the world that don’t have some sort of animation and movement mechanics. But in this article, we will focus on widget animations and application development.

Imagine how poor and annoying your app will be if everything is static. A user who downloads a new app has expectations. One of those expectations is a user-friendly interface that satisfies the user when he interacts with it. Think about it. Will the user feel more pleasure if when he clicks a button the button changes its size and color and performs some kind of animation or when he clicks the button and the button just executes the command that it is meant to execute?

In this article, we will define what exactly animations are and we will discover 3 different animations that you can use to upgrade your app and make it more attractive. We will just use the standard Tkinter library to do this. We don’t need to use other libraries since the animations which I’m gonna show you aren’t complicated. But there are effective.

How do animations work?

Animations in application development refer to the visual effects and transitions that are used to enhance the user experience by adding movement and interactivity to the interface. They are a way to make the user interface elements and content more engaging and responsive.

Animations can include effects such as fading, sliding, rotating, scaling, and more, which are applied to elements like buttons, menus, images, and text. They provide feedback, guide the user’s attention, and create a sense of smoothness and continuity within the application.

Tkinter possesses a very useful function called after. Before calling the function, you must specify the name of your window. Usually in Tkinter, the window is called “root”, so you will write it like this: root.after(). The function takes 2 arguments: the time in milliseconds and another function. This is very useful for creating animations because it repeats the execution of a function of your choice after the amount of time of your choice in a loop.

By combining the after function with conditional statements and movement mechanics, you can create visual effects and animations. Now let’s add some clarity with the examples.

Example 1: Bouncing button

This animation creates a bouncing button. When the button is clicked, it jumps by going up and then quickly down. This creates a cool visual effect and satisfies the user when he clicks somewhere.

Preparation:

from tkinter import *

root = Tk()
root.geometry("1000x600")


button = Button(root, bg="blue", fg="gold", text="ANIMATION",
                font=("Bold", 23), activebackground="#0000DD",
                activeforeground="yellow")

button.place(x=400, y=200)


root.mainloop()

First, we import everything from the Tkinter library. By doing this, we don’t have to write tkinter before every widget’s name or function. If you want to learn more about import statements and aliases, you can check this article.

We then set the window’s properties and we create a button. You can create whatever button you like, it doesn’t matter. We place the button approximately in the middle of the screen and we call the main loop to execute the program.

Screenshot by author

Creating the animation:

button_y = 200


def up():
    global button_y
    if button_y > 140:
        button_y -= 4
        button.place(x=400, y=button_y)
        root.after(12, up)
    elif button_y <= 140:
        down()


def down():
    global button_y
    if button_y < 200:
        button_y += 4
        button.place(x=400, y=button_y)
        root.after(12, down)
    else:
        root.configure(bg="blue")

We need one global variable to create the animation. We gonna call it button_y since it stores the vertical position of the button. The first function is moving the button up. We must check if the position of the button is greater than 140. If it is, we subtract 4 pixels from the variable and update the position of the button. The root.after function is repeating the process every 12 milliseconds until the button_y variable becomes smaller or equal to 140. This creates animation.

When the variable becomes smaller or equal to 140, the down function is called. It does the same but this time the button is moving down until it reaches its original position which is 200. Once it reaches it, the color of the window turns blue. This is an optional part. It just marks the end of the animation. Don’t forget that you must add a command parameter to the button and give it the up function as an argument.

Full code:

Now copy and paste the code into your Python environment and try it.

from tkinter import *

root = Tk()
root.geometry("1000x600")


button_y = 200


def up():
    global button_y
    if button_y > 140:
        button_y -= 4
        button.place(x=400, y=button_y)
        root.after(12, up)
    elif button_y <= 140:
        down()


def down():
    global button_y
    if button_y < 200:
        button_y += 4
        button.place(x=400, y=button_y)
        root.after(12, down)
    else:
        root.configure(bg="blue")


button = Button(root, bg="blue", fg="gold", text="ANIMATION",
                font=("Bold", 23), activebackground="#0000DD",
                activeforeground="yellow", command=up)

button.place(x=400, y=200)


root.mainloop()

Example 2: Visual accumulation

An animation called “visual accumulation” lets the user visualize the process of something rather than just seeing the final result. In this example, we will create a number on the screen with an initial value of 0. When we click a button, we will be able to see how the value of the number is increasing in real time. You can find this kind of animation mostly in mobile games. For example when you finish a level and you collect your coins or points.

Preparation:

from tkinter import *

root = Tk()
root.geometry("1000x600")
root.configure(bg="#222222")


counter = Label(root, text="0", font=("Bold", 27), fg="dark green",
                bg="#222222")

activation_button = Button(root, text="Activate", font=("Arial", 22),
                           bg="blue", fg="white", command=animation)

counter.pack(pady=30)
activation_button.pack()

root.mainloop()

We import everything from the Tkinter library and we set the window’s properties. We create a label that will be storing the value of our number. We also create an activation button to launch the process. We put everything on the screen and we call the main loop.

Note: The animation function which we passed as an argument to the command parameter of the button will be created in a minute.

Screenshot by author

Creating the animation:

random_number = randrange(100, 1000)
current_number = 0


def animation():
    global random_number
    global current_number
    if current_number < random_number:
        current_number += 1
        counter.configure(text=str(current_number))
        root.after(2, animation)

This time we need 2 global variables: one that stores the random number which marks the endpoint at which our number must stop, and a second one which stores the current value of our number.

Then we write the code for the function that is going to handle the animation. We check if the current number is smaller than the random number generated automatically. If it is, we add 1 to our number and we update the text value of the label that shows the value o our number.

The process is repeated every 2 milliseconds until the number reaches the limit generated randomly.

Note: Don’t forget to import the random module at the top of the script.

Full code:

Now copy and paste the code into your Python environment and try it.

from tkinter import *
from random import *

root = Tk()
root.geometry("1000x600")
root.configure(bg="#222222")


random_number = randrange(100, 1000)
current_number = 0


def animation():
    global random_number
    global current_number
    if current_number < random_number:
        current_number += 1
        counter.configure(text=str(current_number))
        root.after(2, animation)


counter = Label(root, text="0", font=("Bold", 27), fg="dark green",
                bg="#222222")

activation_button = Button(root, text="Activate", font=("Arial", 22),
                    bg="blue", fg="white", command=animation)

counter.pack(pady=30)
activation_button.pack()

root.mainloop()

Example 3: Sliding panel

A cool feature for a modern application will be if there’s a panel popping up from somewhere. We’re gonna make one coming from the left side. The panel will be retractable which means that we can make it appear and disappear. This is also a useful animation because you don’t always have the required space to put all the widgets in one window. A sliding panel like this is creating more space. Cool right?

Preparation:

from tkinter import *

root = Tk()
root.geometry("1000x600")

panel = Frame(root, width=320, height=600, bg="green", relief="flat")

show_panel = Button(root, text=">>", font=("Bold", 17), bg="green",
                    fg="white")

panel.place(x=-320, y=0)

show_panel.place(x=-3, y=260)

root.mainloop()

After importing everything from the Tkinter library and setting the window’s properties as usual, we create our panel using a frame as well as a button that we’ll use to open and close the panel.

We make the panel invisible by placing it out of the screen on the left side. We also place the button but this time we make in sort that the button is visible. We call the main loop and we run the program.

Screenshot by author

Creating the animation:

# Global variables
panel_x = -320
show_panel_x = 0


# Functions used to create the animation
def open_panel():
    global panel_x
    global show_panel_x
    if panel_x < 0:
        panel_x += 5
        panel.place(x=panel_x, y=0)
        show_panel_x += 5
        show_panel.place(x=show_panel_x, y=260)
        if panel_x >= 0:
            show_panel.configure(command=close_panel)
            show_panel.configure(text="<<")
        else:
            root.after(5, open_panel)


def close_panel():
    global panel_x
    global show_panel_x
    panel_x -= 5
    panel.place(x=panel_x, y=0)
    show_panel_x -= 5
    show_panel.place(x=show_panel_x, y=260)
    if panel_x <= -320:
        show_panel.configure(command=open_panel)
        show_panel.configure(text=">>")
    else:
        root.after(5, close_panel)

First, we define 2 global variables: the first one stores the “x” position of the panel, and the second one stores the “x” position of the button.

Then we create the function that will open the panel. We check if the “x” position of the panel is smaller than 0. If it is, we move the panel and the button 5 pixels forward every 5 milliseconds. If the “x” position of the panel becomes equal or bigger than 0, we change the command argument of the button to close_panel as well as the text of the button to “<<”. By doing this, we ensure that when we click the button once again, the panel will close.

We do the same with the second function which closes the panel. We move the panel and the button backward until the “x” position of the panel becomes equal to or smaller than -320. When it does, we change the command of the button to open_panel and we also change its text parameter to “>>”.

Note: Don’t forget to set the command parameter of the button to open_panel.

Full code:

Now copy and paste the code into your Python environment and try it.

from tkinter import *

# Window's properties
root = Tk()
root.geometry("1000x600")

# Global variables
panel_x = -320
show_panel_x = 0


# Functions used to create the animation
def open_panel():
    global panel_x
    global show_panel_x
    if panel_x < 0:
        panel_x += 5
        panel.place(x=panel_x, y=0)
        show_panel_x += 5
        show_panel.place(x=show_panel_x, y=260)
        if panel_x >= 0:
            show_panel.configure(command=close_panel)
            show_panel.configure(text="<<")
        else:
            root.after(5, open_panel)


def close_panel():
    global panel_x
    global show_panel_x
    panel_x -= 5
    panel.place(x=panel_x, y=0)
    show_panel_x -= 5
    show_panel.place(x=show_panel_x, y=260)
    if panel_x <= -320:
        show_panel.configure(command=open_panel)
        show_panel.configure(text=">>")
    else:
        root.after(5, close_panel)


# Widgets
panel = Frame(root, width=320, height=600, bg="green", relief="flat")
panel.place(x=-320, y=0)

show_panel = Button(root, text=">>", font=("Bold", 17), bg="green",
                    fg="white", command=open_panel)

show_panel.place(x=0, y=260)

root.mainloop()

Conclusion

The ability to animate elements breathes life into our projects, captivating audiences and providing a rich and immersive experience. Animations are pretty complex, but they create visual effects that fascinate users and satisfy them. Your job as a programmer is to give your best to optimize your application and make it interesting and attractive.

You’ve learned how you can animate most of the widgets you use through 3 practical examples. Remember that to be able to make animations in Python, you must be in touch with 3 main things: movement mechanics, time, and conditional statements. Once you fully understand all of this, you won’t have any problems creating even more complex animations.

Thank you for reading this

Resources

Enjoyed this article?

Share it with your network to help others discover it

Continue Learning

Discover more articles on similar topics