Home > Software design >  Running Tkinter to produce a typing counter. Can't type into entry box while countdown timer is
Running Tkinter to produce a typing counter. Can't type into entry box while countdown timer is

Time:11-18

I'm trying to put together my own script for a typing counter.

# --------------------------------------------------Import Modules-----------------------------------------------------#
from tkinter import *
import time
import random
from threading import Thread

# --------------------------------------------------Set CONSTANTS------------------------------------------------------#
TIMER = 10
FONT_NAME = "Arial"
FONT_HEIGHT = 12
FONT_TYPE = "bold"
BACKGROUND_COLOR = "#A5C9CA"

# --------------------------------------------------Random Text.-------------------------------------------------------#
example_text = [
    "This is going to be a lot of sample text.",
    "This should hopefully be even more sample text."
]


def start_timer():
    t = TIMER
    while t > 0:
        minutes, seconds = divmod(t, 60)
        timer = "{:02d}:{:02d}".format(minutes, seconds)
        print(timer, end=f"\r{timer}")
        canvas.itemconfig(timer_text, text=timer)
        time.sleep(1)
        t -= 1
    # Add function to read the inputted text after timer runs out and print results to user for correct wpm.
    global generated_text
    inputted_user_text = typed_entry_box.get()
    check_wpm(generated_text, inputted_user_text)


def generate_text():
    random_text = random.choice(example_text)
    return random_text


def check_wpm(initial_text, inputted_text):
    initial_list = initial_text.split()
    inputted_list = inputted_text.split()
    del initial_list[len(inputted_list):]
    compared_list = [i == j for i, j in zip(initial_list, inputted_list)]
    wpm = 0
    for n in compared_list:
        if n:
            wpm  = 1
    wpm_label.config(text=f"You typed at {wpm} words per minute.")


# Open Tk Window Box.
window = Tk()
window.title("WPM Test")
window.config(pady=20, padx=20, bg=BACKGROUND_COLOR)

# Create a canvas for the window.
canvas = Canvas(width=500, height=500, bg=BACKGROUND_COLOR, highlightthickness=0)
# Create a text object for the timer.
timer_text = canvas.create_text(250, 25, text="60 Seconds", fill="black", font=(FONT_NAME, 18, FONT_TYPE))
canvas.grid(column=0, row=5)

# Instructions Label at the top.
label_1 = "Test Your Typing Speed. Click the button below and type out the text string shown below. Good Luck!\n" \
          "---------------------------------------------------------------------------------------------------\n\n"
instructions_label = Label(text=label_1, font=(FONT_NAME, 14, FONT_TYPE), bg=BACKGROUND_COLOR)
instructions_label.config(padx=5, pady=5)
instructions_label.grid(row=0, column=0)

# Random text label.
generated_text = generate_text()
random_text_label = Label(text=generated_text, font=(FONT_NAME, 18, FONT_TYPE), bg=BACKGROUND_COLOR)
random_text_label.config(padx=5, pady=5)
random_text_label.grid(row=2, column=0)

# Add label for entry box below.
label_3 = "\n\n-----------------------------------------------------------------------\n\n\n" \
          "Click the button below to start the timer and immediately start typing.\n"
start_typing_label = Label(text=label_3, font=(FONT_NAME, 14, FONT_TYPE), bg=BACKGROUND_COLOR)
start_typing_label.grid(row=3, column=0)

# Add start timer button.
start_timer_button = Button(text="Start Timer", command=start_timer, font=(FONT_NAME, 16, FONT_TYPE))
start_timer_button.config(padx=2, pady=2)
start_timer_button.grid(row=4, column=0)

# Add entry box for the typed text.
typed_entry_box = Entry(width=100, font=(FONT_NAME, 16, FONT_TYPE), bd=5)
typed_entry_box.grid(row=5, column=0)

wpm_label = Label(text="", font=(FONT_NAME, 14, FONT_TYPE), bg=BACKGROUND_COLOR)
wpm_label.grid(row=6, column=0)

# Keeps window open.
window.mainloop()

Besides it looking ugly, I have everything running but when I click the start timer button, I can't type anything into the entry field I created. I'm assuming it's because it is running the timer function but seeing if anyone has an idea for fixing it. Thanks.

CodePudding user response:

Avoid using while loops with time.sleep() in a tkinter app, as it will block the main (UI) thread. Instead, look into the tkinter.after() method, which is useful for situations like this!

t = TIMER

def start_timer():
    global t
    if t:
        minutes, seconds = divmod(t, 60)
        timer = f'{minutes:02d}:{seconds:02d}'
        canvas.itemconfig(timer_text, text=timer)
        t -= 1
        # call this function again aftre 1000mS
        after_id = window.after(1000, start_timer)  
    else:
        window.after_cancel(after_id)  # cancel the countdown
  • Related