Tkinter TtkBootstrap Countdown Timer with Typing Speed Test

Typing speed test by Setting duration from  a countdown timer using ttkbootstrap Meter

Introduction

In this tutorial, we will create an interactive countdown timer using Tkinter and TtkBootstrap. On click of the start button the timer will enable a text box for typing while the timer is running, and disable it once the timer ends. At the end, it will calculate and display the number of characters typed and the typing speed (characters per second).

This project is useful for typing tests, speed challenges, or any timed data entry applications.

Code Breakdown

1. Importing Required Libraries

# Import required modules
import ttkbootstrap as tb
import tkinter as tk
  • ttkbootstrap: Used for styling and interactive meter widget.
  • tkinter: Used for the main graphical user interface (GUI).

2. Function to Start Countdown

def start_countdown():
    # Get time from the interactive meter
    duration = int(meter.amountusedvar.get())

    if duration == 0:
        meter.configure(subtext="Set a value!", bootstyle="danger")
        return

    text_widget.config(state="normal")  # Enable text entry
    text_widget.delete("1.0", tk.END)  # Clear previous text
    countdown(duration, duration)  # Start countdown

Function: start_countdown()

  • Fetches Timer Value: Retrieves the duration set in the interactive meter.
  • Handles Zero Value: If the timer is set to `0`, it displays an error message and stops execution.
  • Enables Text Entry: Unlocks the text widget for the user to start typing by using state attribute.
  • Clears Previous Input: Deletes any existing text in the text box before a new countdown starts.
  • Starts Countdown: Calls the `countdown()` function with the selected duration.

3. Countdown Function

def countdown(remaining_time, total_time):
    if remaining_time >= 0:
        meter.configure(
            amountused=remaining_time, 
            subtext=f"{remaining_time} sec remaining"
        )
        root.after(1000, countdown, remaining_time - 1, total_time)
    else:
        text_widget.config(state="disabled")  # Disable text entry
        typed_text = text_widget.get("1.0", tk.END).strip()
        char_count = len(typed_text)
        typing_speed = char_count / total_time if total_time > 0 else 0
        
        meter.configure(
            subtext=f"Time Over! {char_count} chars, {typing_speed:.2f} cps", 
            bootstyle="danger"
        )

Function: countdown()

  • Updates Timer: Displays the remaining time on the meter every second.
  • Handles Window Closure: Ensures that the countdown stops if the window is closed.
  • Recursively Calls Itself: Uses root.after(1000, countdown, remaining_time - 1, total_time) to update the timer every second.
  • Stops Countdown at Zero: When the timer reaches `0`, it locks the text box and calculates the typing speed.
  • Computes Typing Speed: Counts characters typed and calculates speed in characters per second (CPS).
  • Displays Final Message: Updates the meter to show the number of characters typed and the typing speed.

4. Creating the Main Application Window

# Create main window
root = tb.Window(themename="superhero")
root.title("Interactive Countdown Timer")

# Interactive Meter Widget
meter = tb.Meter(root, bootstyle="warning", interactive=True,
                 stripethickness=6, meterthickness=20, 
                 amountused=33, amounttotal=60, 
                 subtext="Set Time & Click Start")
meter.grid(row=0, column=0, padx=20, pady=20)

# Text Widget (Initially Disabled)
text_widget = tk.Text(root, height=5, width=40, state="disabled")
text_widget.grid(row=1, column=0, padx=20, pady=10)

# Start Button
start_button = tb.Button(root, text="Start", bootstyle="success", command=start_countdown)
start_button.grid(row=2, column=0, pady=10)

root.mainloop()

import ttkbootstrap as tb
import tkinter as tk

# Function to start countdown
def start_countdown():
    """ Starts the countdown timer and enables the text box. """
    
    duration = int(meter.amountusedvar.get())  # Get value from meter
    
    if duration == 0:
        meter.configure(subtext="Set a value!", bootstyle="danger")
        return

    text_widget.config(state="normal")  # Enable text entry
    text_widget.delete("1.0", tk.END)  # Clear previous text
    #text_widget.focus() # Keeping cursor inside Text widget at start
    countdown(duration, duration)  # Start countdown

# Countdown function using after()
def countdown(remaining_time, total_time):
    """ Updates the meter every second and disables the text box when time is up. """
    
    if remaining_time >= 0:
        if root.winfo_exists():  # Check if window is still open
            meter.configure(
                amountused=remaining_time, 
                subtext=f"{remaining_time} sec remaining"
            )
            root.after(1000, countdown, remaining_time - 1, total_time)
        else:
            return  # Stop if window is closed
    else:
        # Disable text entry when time is over
        text_widget.config(state="disabled")  
        
        # Get the text entered by the user
        typed_text = text_widget.get("1.0", tk.END).strip()  
        
        # Count the number of characters typed
        char_count = len(typed_text)  
        
        # Calculate typing speed (characters per second)
        typing_speed = char_count / total_time if total_time > 0 else 0  
        
        # Update the meter with typing speed info
        meter.configure(
            subtext=f"Time Over! {char_count} chars, {typing_speed:.2f} cps", 
            bootstyle="danger"
        )  

# Create main window
root = tb.Window(themename="superhero")  # Change the theme if needed
root.title("www.plus2net.com Interactive Countdown Timer")

# Interactive Meter Widget
meter = tb.Meter(
    root, bootstyle="warning", interactive=True, 
    stripethickness=6, meterthickness=20, 
    amountused=33, amounttotal=60, 
    subtext="Set Time & Click Start"
)
meter.grid(row=0, column=0, padx=20, pady=20)

# Text Widget (Initially Disabled)
text_widget = tk.Text(root, height=5, width=40, state="disabled")
text_widget.grid(row=1, column=0, padx=20, pady=10)

# Start Button
start_button = tb.Button(
    root, text="Start", bootstyle="success", 
    command=start_countdown
)
start_button.grid(row=2, column=0, pady=10)

# Run the application
root.mainloop()


Ttkbootstrap Meter bootstyle option using range Two Interlinked Meters Displaying number of chars entered in Text widget using Meter
ttkbootstrap ttkbootstrap Meter
Monitor System Performance using ttkbootstrap Meter and psutil

Subscribe to our YouTube Channel here


Subscribe

* indicates required
Subscribe to plus2net

    plus2net.com







    Python Video Tutorials
    Python SQLite Video Tutorials
    Python MySQL Video Tutorials
    Python Tkinter Video Tutorials
    We use cookies to improve your browsing experience. . Learn more
    HTML MySQL PHP JavaScript ASP Photoshop Articles FORUM . Contact us
    ©2000-2024 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer