Calculate the time between a range of key events in Python

1.1k views Asked by At

As a part of my self learning projects, I decided to create an application in Python that listens to certain keyevents and finds the amount of time it takes to type a word. It's been more than 12 hours of straight debugging and loop/logic experiments and all I could do is this:

import Tkinter
import time

KeyWatch = Tkinter.Tk()

WordBoxLegend = Tkinter.Label(KeyWatch, text="Type the required word")
WordBoxLegend.pack(side=Tkinter.LEFT)

WordBox = Tkinter.Entry(KeyWatch)
WordBox.pack(side=Tkinter.LEFT)

TextBoxLegend = Tkinter.Label(KeyWatch, text="Type the same to calculate the time")
TextBoxLegend.pack(side=Tkinter.LEFT)

TextBox = Tkinter.Entry(KeyWatch) 
TextBox.pack(side=Tkinter.RIGHT)

WordBox.focus()

def pressed(keyevent):
    WordRequire = WordBox.get()
    LetterList = tuple(WordRequire)
    start = time.time()
    LastLetter = str(LetterList[-1])
    print len(LetterList())
    print LetterList[len(LetterList)]
    if keyevent.char in LetterList:
        for x in range(0, len(LetterList)):
            if LetterList[x] != LastLetter:
                print LetterList[x]
                TextBox.unbind(str(LetterList[x]))
                TextBox.bind(str(LetterList[x+1]))
            elif str(LetterList[x]) == LastLetter and x == len(LetterList):
                stop = time.time()
                totaltime = stop - start
                print LetterList[x]
                print totaltime
                break
                TextBox.unbind(LetterList[x])
            else:
                TextBox.unbind(str(LetterList))     
    else:   
        print "Type only the letters from" +str(LetterList)

KeyWatch.mainloop()
TextBox.bind("<Key>", pressed)

Gist

After I bind keys and pass it to the pressed method, I am not sure how to unbind that particular key and bind the next value in the tuple.

Expected Result

If I type the word, 'Obliteration' the program should tell me how much time it takes from the keyevent "O" to keyevent "n".

What is the Expected Result for events <Key> in Tkinter?

1

There are 1 answers

3
Dan O'Boyle On BEST ANSWER

This was fun!

I rewrote your code with pep8 in mind.

Variable names were adjusted for readability.

There were some logical mistakes in how you define the start time.

Consider that every time a key is pressed, pressed() is called. There was also a hidden problem with how the key press was being detected. Your code had:

word_repeat_box.bind("<Key>", pressed)

"<KEY>" Catches the pressing of the key, you want the RELEASE of the key. Otherwise the function is called before the key is released, and the value entered into the repeat box. I changed it to use <KeyRelease> instead. (feel free to run the code with my debugging to compare "<KEY>" and "<KeyRelease>")

import Tkinter
import time

start = None
stop = None

key_watcher = Tkinter.Tk()

word_entry_label = Tkinter.Label(key_watcher, text="Type the required word")
word_entry_label.pack(side=Tkinter.LEFT)

word_entry_box = Tkinter.Entry(key_watcher)
word_entry_box.pack(side=Tkinter.LEFT)

word_repeat_label = Tkinter.Label(key_watcher,
                           text="Type the same to calculate the time")

word_repeat_label.pack(side=Tkinter.LEFT)

word_repeat_box = Tkinter.Entry(key_watcher)
word_repeat_box.pack(side=Tkinter.RIGHT)

word_entry_box.focus()


def pressed(keyevent):
  # print keyevent  #Left this in for debugging, you can see the key press.
  # start = time.time()  #start time will be reset every time this is called.
  first_word = word_entry_box.get()
  first_word_size = len(first_word)
  first_letter_list = tuple(first_word)
  first_word_first_letter = str(first_letter_list[0])
  first_word_last_letter = str(first_letter_list[-1])

  repeat_word = word_repeat_box.get()
  repeat_word_size = len(repeat_word)

  if repeat_word_size > 0:
      repeat_letter_list = tuple(repeat_word)
      repeat_word_first_letter = str(repeat_letter_list[0])
      repeat_word_last_letter = str(repeat_letter_list[-1])

  # Lets see whats happening on each press:
  print "Pressed:", keyevent.char
  print "First word:", first_word, "size", first_word_size
  print "repeat word:", repeat_word, "size", repeat_word_size

  # now that all the things we want to look at are defined, lets logic:

  if repeat_word_size == 1:
      global start
      start = time.time()
      print "time started!", start

  if first_word_size == repeat_word_size:
      print "words are same size"

      if first_word_last_letter == repeat_word_last_letter:
          global end
          stop = time.time()
          totaltime = stop - start
          print "Total time taken", totaltime

word_repeat_box.bind("<KeyRelease>", pressed)
key_watcher.mainloop()  # mainloop() should be called last, it starts your loop

Output with Debugging:

Pressed: t
First word: test size 4
repeat word: t size 1
time started! 1434046015.13
Pressed: e
First word: test size 4
repeat word: te size 2
Pressed: s
First word: test size 4
repeat word: tes size 3
Pressed: t
First word: test size 4
repeat word: test size 4
words are same size
Total time taken 1.69620299339

This could probably be done without globals, maybe with a recursive call, but I'll leave that for you to solve.