Search code examples
python-3.xfor-loopmatrixtkinterkeypress

Python: registering key presses and saving responses to an array or matrix


I am very new to Python, and I have been struggling with trying to find an answer to this question for a while now.

I am using Python 3.5 to write an experiment script. I would like to write a script that loops through a number of trials and saves which key was pressed for each trial in a matrix. I am coding in Python's IDLE.

I attempted to write something using tkinter, but cannot get it to loop through the trials and store them properly in the matrix. It is important that pressing the "Enter" key after the key press is not required. Also, I know msvcrt.getch() will not work in IDLE (I would like to try continue using IDLE), and I cannot use Psychopy2 (for reasons that are too detailed to explain here).

I am open to any suggestions/recommendations! Thank you so much in advance for your time.

[I posted my draft code below to try to give people a better idea of what I am trying to do. I know it is incorrect, though!]

import tkinter as tk
import numpy

num_trials = 5    
response_matrix = numpy.zeros([num_trials,1]) # creating a matrix to fill

for x in range(0,num_trials-1): # looping through trials 0 to 4
    def keypress(event):
        key = event.char
       if key == "1":
           print("1 pressed")
           response_matrix[x]=1 # assigning what key pressed to the matrix 
       elif key == "2":
           print("2 pressed")
           response_matrix[x]=2
       elif key == "3":
           print("3 pressed")            
           response_matrix[x]=3
       elif key == "4":
           print("4 pressed")
           response_matrix[x]=4
       elif x == 4: # the final trial
           print("done")
           break
root = tk.Tk()
root.bind_all('<Key>', keypress)
root.update()

Solution

  • The two big mistakes are trying to do repetitions with a loop and defining the function within the loop. Putting characters in a numpy array is likely not what you want. Anyway, you can build on the following.

    import tkinter as tk
    
    num_trials = 5
    trials =  0
    responses = []
    
    def keypress(event):
        global trials
        key = event.char
        if key.isdigit() and trials < num_trials:
            print("%s pressed" % key)
            responses.append(key)
            trials += 1
            if trials == num_trials:
                print('Responses were %s.' % responses)
                print('Hit [X] to quit.')
    
    print('Enter %s digits.' % num_trials)
    root = tk.Tk()
    root.bind('<Key>', keypress)
    root.mainloop()
    

    In a real program, you should probably put messages to user in widgets, and only use print for debugging.