hrebikmilan3
hrebikmilan3

Reputation: 1

Python Rectangle Color Animation

How could I make a third button that turns the rectangles from grey to red, one by one. (Example: Rectangle 1 lights up, then it waits a second and then rectangle 2 lights up). I have tried to do it by putting time.sleep() between every single w.create_rectangle, but that didnt work. How could I do this, please help me.

import time
master = Tk()

canvas_width = 280
canvas_height = 50
w = Canvas(master, width=canvas_width, height=canvas_height)
w.pack()

w.create_rectangle(0, 0, 25, 25, fill="grey")
w.create_rectangle(25, 0, 50, 25, fill="grey")
w.create_rectangle(50, 0, 75, 25, fill="grey")
w.create_rectangle(75, 0, 100, 25, fill="grey")
w.create_rectangle(100, 0, 125, 25, fill="grey")
w.create_rectangle(125, 0, 150, 25, fill="grey")
w.create_rectangle(150, 0, 175, 25, fill="grey")
w.create_rectangle(175, 0, 200, 25, fill="grey")
w.create_rectangle(200, 0, 225, 25, fill="grey")
w.create_rectangle(225, 0, 250, 25, fill="grey")

def uno():
    w.create_rectangle(0, 0, 25, 25, fill="red")
    w.create_rectangle(25, 0, 50, 25, fill="red")
    w.create_rectangle(50, 0, 75, 25, fill="red")
    w.create_rectangle(75, 0, 100, 25, fill="red")
    w.create_rectangle(100, 0, 125, 25, fill="red")
    w.create_rectangle(125, 0, 150, 25, fill="red")
    w.create_rectangle(150, 0, 175, 25, fill="red")
    w.create_rectangle(175, 0, 200, 25, fill="red")
    w.create_rectangle(200, 0, 225, 25, fill="red")
    w.create_rectangle(225, 0, 250, 25, fill="red")
def dos():  
    w.create_rectangle(0, 0, 25, 25, fill="grey")
    w.create_rectangle(25, 0, 50, 25, fill="grey")
    w.create_rectangle(50, 0, 75, 25, fill="grey")
    w.create_rectangle(75, 0, 100, 25, fill="grey")
    w.create_rectangle(100, 0, 125, 25, fill="grey")
    w.create_rectangle(125, 0, 150, 25, fill="grey")
    w.create_rectangle(150, 0, 175, 25, fill="grey")
    w.create_rectangle(175, 0, 200, 25, fill="grey")
    w.create_rectangle(200, 0, 225, 25, fill="grey")
    w.create_rectangle(225, 0, 250, 25, fill="grey")


button1 = Button(master, text="zasviet", command=uno)
button1.pack(side='left', padx=10)
button2 = Button(master, text="zhasni", command=dos)
button2.pack(side='left', padx=10)
button3 = Button(master, text="animacia", command=tres)
button3.pack(side='left', padx=10)

Upvotes: 0

Views: 109

Answers (1)

Mike - SMT
Mike - SMT

Reputation: 15226

You should never use sleep() in the same thread that Tkinter is using. Due to Tkinter being a single thread GUI you cannot use sleep() and things that block the main loop like while statements if you want your GUI to work properly.

Instead you want to use after() as this is exactly what it is designed for. To managed things time wise without using sleep().

after() takes a few arguments. the 1st is time in milliseconds so one second is 1000 milliseconds. The second is the function name you are calling and the third can be an arguments. It will look something like this root.after(1000, func_name, arg).

In this case we should create all your canvas objects in a list so that we can simply update those objects later with the colors you want rather than recreating the objects on top of the previous.

In the below code I have cleaned up your code a bit and added the functionality to perform this task. Let me know if you have any questions.

import tkinter as tk


master = tk.Tk()
rectangle_list = []
canvas_width = 280
canvas_height = 50
w = tk.Canvas(master, width=canvas_width, height=canvas_height)
w.pack()


# Create the list of rectangle objects to be used later.
for i in range(10):
    x = i * 25
    if i == 1:
        rectangle_list.append(w.create_rectangle(0, 0, 25, 25, fill="grey"))
    else:
        rectangle_list.append(w.create_rectangle(x-25, 0, x, 25, fill="grey"))


# manage color change loop based on index of rectangle list.
def uno(ndex=0):
    if ndex < len(rectangle_list):
        w.itemconfig(rectangle_list[ndex], fill='red')
        master.after(1000, uno, ndex+1)


def dos(ndex=0):
    if ndex < len(rectangle_list):
        w.itemconfig(rectangle_list[ndex], fill='grey')
        master.after(1000, dos, ndex+1)


tk.Button(master, text="zasviet", command=uno).pack(side='left', padx=10)
tk.Button(master, text="zhasni", command=dos).pack(side='left', padx=10)
tk.Button(master, text="animacia").pack(side='left', padx=10)
master.mainloop()

The below image just illustrates that colors are being changed in order and you can press more than one button during the color changes to create a pattern.

enter image description here

Upvotes: 1

Related Questions