Typing Speed Test


Professional project
Python code solution and explanation
Tkinter GUI

Introduction

A typing speed test is a tool used to measure a person’s typing proficiency. It involves typing a passage of text as quickly as possible within a set time frame. This result is expressed in words per minute (WPM).

You might have come across an online typing speed test before, but today we’re going to make one using python, for you to show off to your friends, and see who’s the fastest typer!

STEP BREAKDOWN

Let’s break this program down into smaller steps.

  1. Make the screen
  2. Display all widgets (label, textbox, button)
  3. Display words to type
  4. Timer system
  5. Check typing speed
SOLUTION

This is what we’re going to import. I used a python file called english_words.py, which contains one variable, which has many simple words stored. You can also use your own words list for this project.

import tkinter as tk
from english_words import all_words
import time

english_words.py

all_words = """
which
there
their
about
would
etc.. lots more words
"""

First, let’s start off by making the GUI window. The window will originally be white.

# window
window = tk.Tk()
window.title("Typing Speed Test")
window.geometry('575x360')
window.configure(bg="white")

First, we’re going to split the all_words variable and store it into words_split. Then we have a simple mechanism for adding a new line every 10 words, so all the words can be displayed on the screen. This is saved to words_text.

# words
words_split = all_words.split()
words_text = ""
for word in range(0, 100):
    if word % 10 == 0 and word != 0:
        words_text += f"{words_split[word]} \n"
    else:
        words_text += f"{words_split[word]} "

words_label = tk.Label(window, text=words_text, font=('Arial', 14), bg="lightpink")
words_label.pack(padx=10, pady=10)

Now we can make a timer label, which will correspond display the seconds passed since the user started typing.

# timer
seconds_passed = 0
timer_label = tk.Label(window, text=seconds_passed, font=('Arial', 24), bg="white", fg="lightgreen")
timer_label.pack()

Then we will make a start button so that the user can press the button if they’re ready, which will start a timer. We can make a function called start_timer(), and pass it on as the command.

start_button = tk.Button(window, width=7, text="Start", fg="lightgreen", command=start_timer)
start_button.pack()

We can finally make a textbox, where the user will type the words.

# text box
textbox = tk.Text(window, height=2, font=('Arial', 12), bg="white")
textbox.pack(padx=10, pady=10)

Finally, we can add window.mainloop() so the code keeps running.

window.mainloop()

Now that we’re done with the GUI window of our program, we can now start with the functionality. We already entered a command for when start_button is clicked. Using this function, we can trigger more functions so we only need to mention one command in the start_button.

Once start_button is clicked, we can make the window black and change the colors of every widget. We can also destroy start_button, because there is no use for the button anymore. Once the screen looks different, we will mention another function, called add_second().

def start_timer():
    window.config(bg="black")
    words_label.config(bg="black", fg="lightgrey")
    timer_label.config(bg="black")
    start_button.destroy()
    add_second()

How are we going to check that one minute has been up since the user started typing? Every second that time goes by, the timer_label will be updated and displayed by being redirected its own function. After a minute has been done, we can link to another function called check_typing_speed().

def add_second():
    global seconds_passed
    seconds_passed += 1
    timer_label.configure(text=f'{seconds_passed}')

    # call this function again after one second if the time is not over.
    window.after(1000, add_second)
    window.after(60000, check_typing_speed)

The simplistic logic I used was every correct word typed will be counted toward your wpm. For example, if I typed 50 words in total but 5 were typed incorrectly, then I will have a speed of 45wpm

After a minute has passed, check_typing_speed() will be called. It will grab all the text from textbox. This text will be turned into a list, called text. Now we will compare every word the user typed to the original set of words. For position in range(len(text)), if the typed word is the same as the original word, we will append the word to a list called correct. Else if the typed word isn’t the original word, then it will be appended to a list called incorrect.

Then the window will be destroyed, and then a message of your wpm will be displayed.

    window.destroy()
    print(f"Great job! You have a speed of {len(correct)}wpm. Your raw speed is {len(text)}wpm.")
    print(f"Incorrect words: {incorrect}")
FINAL code

To view my full code, please visit my GitHub repository: https://github.com/Gursehaj-Singh/typing-speed-test

main.py

import tkinter as tk
from english_words import all_words
import time


# ---------- FUNCTIONS ---------- #

def start_timer():
    window.config(bg="black")
    words_label.config(bg="black", fg="lightgrey")
    timer_label.config(bg="black")
    start_button.destroy()
    add_second()


def add_second():
    global seconds_passed
    seconds_passed += 1
    timer_label.configure(text=f'{seconds_passed}')

    # call this function again after one second if the time is not over.
    window.after(1000, add_second)
    window.after(60000, check_typing_speed)


def check_typing_speed():
    time.sleep(1)
    text_input = textbox.get(1.0, "end")
    text = text_input.split()
    words = words_split
    correct = []
    incorrect = []
    for pos in range(len(text)):
        if text[pos] != words[pos]:
            incorrect.append(f"{words[pos]}: {text[pos]}")
        else:
            correct.append(words[pos])

    window.destroy()
    print(f"Great job! You have a speed of {len(correct)}wpm. Your raw speed is {len(text)}wpm.")
    print(f"Incorrect words: {incorrect}")


# ---------- GUI ---------- #

# window
window = tk.Tk()
window.title("Typing Speed Test")
window.geometry('575x360')
window.configure(bg="white")

# words
words_split = all_words.split()
words_text = ""
for word in range(0, 100):
    if word % 10 == 0 and word != 0:
        words_text += f"{words_split[word]} \n"
    else:
        words_text += f"{words_split[word]} "

words_label = tk.Label(window, text=words_text, font=('Arial', 14), bg="lightpink")
words_label.pack(padx=10, pady=10)

# timer
seconds_passed = 0
timer_label = tk.Label(window, text=seconds_passed, font=('Arial', 24), bg="white", fg="lightgreen")
timer_label.pack()

# start
start_button = tk.Button(window, width=7, text="Start", fg="lightgreen", command=start_timer)
start_button.pack()

# text box
textbox = tk.Text(window, height=2, font=('Arial', 12), bg="white")
textbox.pack(padx=10, pady=10)

window.mainloop()
Example run
Before player starts
Once the player pressed start button
1 minute has gone by and test is done

Great job! You have a speed of 30wpm. Your raw speed is 32wpm.
Incorrect words: [‘there: theer’, ‘would: world’]

Process finished with exit code 0

,

One response to “Typing Speed Test”