noocoder777
noocoder777

Reputation: 62

How to hide and show canvas in tkinter python?

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()

Upvotes: 0

Views: 78

Answers (1)

acw1668
acw1668

Reputation: 47093

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():

  1. countdown - how long the animation should be running in ms
  2. delay - sleep period between moving of the dot in ms

Updated 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()

Upvotes: 2

Related Questions