Wakefield's Daily Tips

Use keyboard components instead of event.getKeys()

The keyboard component in PsychoPy Builder uses the Keyboard class, which has better timing than the older event module. If you want to identify whether a key has been pressed in Each Frame then code of the form

keys = event.getKeys()

can be replaced with

keys = []
if key_resp.keys: # Keyboard component should store all keys and not force the end of the routine
    if len(key_resp.keys) > nKeys: # Add nKeys = 0 in Begin Routine
        keys = [key_resp.keys[-1]] # keys must be a list
        nKeys = len(key_resp.keys)

In both cases the code can be followed by:

if len(keys):
    if 'return' in keys and len(displayText)>1: # Ensures something has been typed
        continueRoutine=False
    elif 'space' in keys:
        displayText += ' '
    elif 'backspace' in keys: # Doesn't work online
        displayText=displayText[:-1]
    elif 'N/A' in keys: # Several keys return N/A online
        displayText=displayText[:-1]
    elif 'comma' in keys:
        displayText += ','
    elif 'semicolon' in keys:
        displayText += ';'
    elif 'period' in keys:
        displayText += '.'
    elif 'minus' in keys:
        displayText += '-'
    elif 'equal' in keys:
        displayText += '='
    elif 'bracketleft' in keys:
        displayText += '['
    elif 'bracketright' in keys:
        displayText += ']'
    elif 'lshift' in keys or 'rshift' in keys:
        modify = True # Capitalise the next letter
    elif modify==False:
        displayText += keys[0]
    else:
        if '1' in keys:
            displayText += '!'
        elif '2' in keys:
            displayText += '\"'
        elif '3' in keys:
            displayText += '£'
        elif '4' in keys:
            displayText += '$'
        elif '5' in keys:
            displayText += '%'
        elif '6' in keys:
            displayText += '^'
        elif '7' in keys:
            displayText += '&'
        elif '8' in keys:
            displayText += '*'
        elif '9' in keys:
            displayText += '('
        elif '0' in keys:
            displayText += ')'
        elif 'minus' in keys:
            displayText += '_'
        elif 'equal' in keys:
            displayText += '+'
        else:
            displayText += keys[0].upper() 
        modify = False

This code requires the following in Begin Routine

nKeys = 0
displayText = ''

In cases where the Keyboard class is insufficient for your needs, an editable textbox using the following code might help. However, it fails if participants move their cursor away from the end of the string using the left arrow key.

if len(textbox.text) > nKeys:
    keys = textbox.text[-1] # keys doesn't need to be a list because it can only have one character
elif len(textbox.text) < nKeys:
    pass # Add code here if you want to register that backspace has been pressed
nKeys = len(textbox.text)

One final note. on today’s tip. If you are unable to run a simple experiment that has a keyboard component, try changing the keyboard backend in Experiment Settings / Input. There seem to be some compatibility issues with ioHub which are fixed by switching to PsychToolbox.