psychopy.org | Reference | Downloads | Github

Text entry code from old experiment does not work in PsychoPy 3.1

OS: Win10
PsychoPy version: 3.1.5
Standalone

I have some old experiments that no longer work in PsychoPy3. I’m trying to update them for PsychoPy3 standalone and online. The problem (besides being my lack of experience with more complicated code) right now is text entry. This code worked prior to PsychoPy 3:

Begin Experiment

inputText = ''

Begin Routine

theseKeys = ''
shift_flag = FALSE

Each Frame

n= len(theseKeys)
i = 0
while i < n:

    if theseKeys[i] == 'return':
        # pressing RETURN means time to stop
        continueRoutine = False
        break

    elif theseKeys[i] == 'backspace':
        inputText = inputText[:-1]  # lose the final character
        i = i + 1

    elif theseKeys[i] == 'space':
        inputText += ' '
        i = i + 1

    elif theseKeys[i] in ['lshift', 'rshift']:
        shift_flag = True
        i = i + 1

    else:
        if len(theseKeys[i]) == 1:
            # we only have 1 char so should be a normal key, 
            # otherwise it might be 'ctrl' or similar so ignore it
            if shift_flag:
                inputText += chr( ord(theseKeys[i]) - ord(' '))
                shift_flag = False
            else:
                inputText += theseKeys[i]

        i = i + 1

End Routine

thisExp.addData('inputText', inputText)

Now when I try to run this code, I get this error:

I suspect there is a simpler way to do this now, but everything I can find online is this or older. I don’t want a dialogue box.

Does anyone have a working way to enter and record keyed text? I’d love it in Python and JavaScript. Thanks very much for the help.

In case anyone else is having this issue, I just found some different code that works in PsychoPy 3. I’ve modified it for my purposes. So, here’s my code, then afterwards is the link to the original code.

Begin Routine:

cursorCounter=0
cursorVariable='|'
captured_string=''
subject_response_finished=False
trial_clock=core.Clock()

Each Frame:

if cursorCounter >= 30:
    if cursorVariable=='|':
        cursorVariable=' '
    else:
        cursorVariable='|'
    cursorCounter=0
cursorCounter+=1
if trial_clock.getTime() >= 1:
    subject_response_finished=True

if subject_response_finished:
    final_response=captured_string
for key in event.getKeys():
    if key in ['escape']: 
        core.quit()
    elif key in ['delete','backspace']:
        captured_string = captured_string[:-1] 
    elif key in ['space']:
        captured_string = captured_string+' '
    elif key in ['lshift','rshift','up','down','left','right']:
        pass
    else: 
        captured_string = captured_string+key

End Routine:
thisExp.addData('response',final_response)

Link - look for Andrew’s post that starts “Oops sorry”: https://groups.google.com/forum/#!topic/psychopy-users/lE_bTMHUAoU

If I figure out the JavaScript, I will come back here and add that as well.

This is just since 3.1.x

Keys returned by the new Keyboard class aren’t simply strings now. They have additional data attached to them like timestamps. if you do print(dir(key)) you’ll find their fields. That’s why your code to test the length didn’t work - you’re doing something we hadn’t imagined was necessary - but you could use len(key.name) to work as before.

Hi Jon,

Thanks, this is an FYI as the original code is not mine.

The code you explain (it’s somewhat over my head - super novice) may not be necessary. I’m trying to update an old FOK (feeling of knowing) task written in PsychoPy somewhere around 1.8 to my current version of 3.1.5. I’ve got it working now, but I did change a LOT of things from the original code (partially because I didn’t understand a good portion of the original code). So, it may not be necessary at all to test length (I can’t think of why it would be). The code I posted above is actually working better than the original code. Just didn’t want you to work on something that is probably not necessary.

Cool, Ive marked that as the solution. FYI The reason the other code was checking length was to see if the keypress looks like a character (‘a’ has length 1) or something else (‘left’ has length 4). Your new code does that with explicit checks for each key

Actually, here is another solution for those who need to go online. I couldn’t get the code above translated into JS. It doesn’t like core.Clock(). I tried a ton of other things, but could not get it to work. Then I accidentally found a discourse page asking about text entry (never came up when I was searching for text entry). That page sends you here:

On that pavlovia page is BOTH the python and the JS for text entry. It doesn’t include a cursor like the code above, but works just as well.