I have created a moving dot animation in tkinter canvas to represent loading. Whenever I input something to the text widget, it should immediately show this moving animation. After 5 seconds, it should disappear. This is the needed functionality. I don't know whats wrong with the below code. Can someone help me achieve what I've described.
import tkinter as tk
from tkinter import ttk
import time
def animate_dot(canvas, dot, dx):
canvas.move(dot, dx, 0)
x_pos = canvas.coords(dot)[0]
if x_pos >= 150 or x_pos <= 50:
dx *= -1 # Change direction when reaching the edge
canvas.after(10, animate_dot, canvas, dot, dx) # Increase speed by reducing the delay
def send_message(event=None):
message = message_entry.get(1.0, "end-1c")
message = message.strip()
message_entry.delete(1.0, tk.END)
message_entry.update()
if not message:
pass
else:
canvas1.place(x=510,y=90)
canvas1.update()
animate_dot(canvas1, dot, dx)
time.sleep(5)
canvas1.forget()
root = tk.Tk()
root.title("Chat")
# Maximize the window
root.attributes('-zoomed', True)
canvas1 = tk.Canvas(root, width=250, height=70, bg="white", borderwidth=0, highlightthickness=0)
# Display "Loading" text
loading_text = canvas1.create_text(50, 50, text="Loading", anchor="e")
# Create a black dot
dot = canvas1.create_oval(50, 40, 60, 50, fill="black")
dx = 1 # Increase the initial movement speed
message_entry = tk.Text(root, padx=17, insertbackground='white', width=70, height=1, spacing1=20, spacing3=20, font=('Open Sans', 14))
message_entry.pack(side=tk.LEFT, padx=(500, 0), pady=(0, 70))
message_entry.bind("<Return>", send_message)
#message_entry.bind("<Button-1>", click
message_entry.focus_set()
root.mainloop()
You should avoid calling time.sleep()
in the main thread because it will block tkinter mainloop()
from handling pending events and updates.
You should check whether the animation should be stopped inside animate_dot()
. Suggest to add two arguments to animate_dot()
:
countdown
- how long the animation should be running in msdelay
- sleep period between moving of the dot in msUpdated code:
# added arguments countdown (default 5000ms) and delay (default 10ms)
def animate_dot(canvas, dot, dx, countdown=5000, delay=10):
canvas.move(dot, dx, 0)
x_pos = canvas.coords(dot)[0]
if x_pos >= 150 or x_pos <= 50:
dx *= -1 # Change direction when reaching the edge
if countdown > 0:
# keep animation
canvas.after(delay, animate_dot, canvas, dot, dx, countdown-delay, delay) # Increase speed by reducing the delay
else:
# stop animation, so remove the canvas
canvas1.place_forget()
def send_message(event=None):
message = message_entry.get(1.0, "end-1c")
message = message.strip()
message_entry.delete(1.0, tk.END)
message_entry.update()
if not message:
pass
else:
canvas1.place(x=510,y=90)
canvas1.update()
animate_dot(canvas1, dot, dx)
# don't call sleep() here
#time.sleep(5)
#canvas1.forget()