pythontkinterlabelcountdowncustomtkinter

how to update a label in countdown with customtkinter


I was creating a sound recorder and when i wanted to create a countdown i face problems

here's my code

from customtkinter import *
import sounddevice
from scipy.io.wavfile import write
import time


recorder = CTk()


info = CTkLabel(recorder, text="Enter the duration of recording", font=("fb agency", 30))
info.pack()


seconds = CTkEntry(recorder, placeholder_text="Enter:")
seconds.pack()


def record():
    global seconds

    fs = 44100
    recorded_voice = sounddevice.rec((int(seconds.get()) * fs), samplerate=fs, channels=2)
    second_countdown = int(seconds.get())
    while second_countdown > 0:
        print(second_countdown)
        time.sleep(1)
        second_countdown -= 1
    print("Finished!")
    sounddevice.wait()
    write("recorded voice.wav", fs, recorded_voice)




record_btn = CTkButton(recorder, text="RECORD", fg_color="red", command=record)
record_btn.pack()

remaining_time = CTkLabel(recorder, text="not recording")
remaining_time.pack()

recorder.mainloop()

I tried some methodes but all of them had one error:

when the button pressed even the button stoped and after the record the countdown started


Solution

  • time.time() is a blocking function, you should never call code that blocks the execution of the mainloop or your application will freeze because it will not be able to respond to events or update.

    In your case you can use after() together with wait_variable(), for example:

    import customtkinter as ctk
    import sounddevice
    from scipy.io.wavfile import write
    
    
    recorder = ctk.CTk()
    
    info = ctk.CTkLabel(
        recorder,
        text="Enter the duration of recording",
        font=("fb agency", 30)
    )
    info.pack()
    
    seconds = ctk.CTkEntry(recorder, placeholder_text="Enter:")
    seconds.pack()
    
    
    def record():
        fs = 44100
        rec_time = int(seconds.get())
        record_btn.configure(state=ctk.DISABLED)
        recorded_voice = sounddevice.rec(rec_time * fs, samplerate=fs, channels=2)
        for remaining_secs in range(rec_time, -1, -1):
            recorder.after(1000, remaining_time_var.set, str(remaining_secs))
            recorder.wait_variable(remaining_time_var)
        sounddevice.wait()
        write("recorded voice.wav", fs, recorded_voice)
        remaining_time_var.set("Recording completed")
        record_btn.configure(state=ctk.NORMAL)
    
    
    record_btn = ctk.CTkButton(
        recorder,
        text="RECORD",
        fg_color="red",
        command=record
    )
    record_btn.pack()
    
    remaining_time_var = ctk.StringVar()
    remaining_time_var.set("not recording")
    remaining_time = ctk.CTkLabel(recorder, textvariable=remaining_time_var)
    remaining_time.pack()
    
    recorder.mainloop()
    

    enter image description here

    after()schedules the execution of a callback after a specified time. wait_variable() waits for the variable to update. Both functions do not block the mainloop so the app remains responsive during wait periods.

    Both scipy.io.wavfile.write and sounddevice.wait() are also blocking, but should not cause any problems if you don't intend to make relatively long recordings.