psychopy.org | Reference | Downloads | Github

How to deal with Ctrl, Shift, Caps Lock Keys with text input code?

I’m not a native English speaker and I have no prior knowledge about programming language, so my words may sound awkward. Please understand. :slight_smile:

OS (e.g. Win10): macOS Catalina
PsychoPy version (e.g. 1.84.x): PsychoPy3 v.3.2.4
Standard Standalone? (y/n) If not then what?: I don’t know…

What are you trying to achieve?:

I’d like to make a text input box where participants can type 1-2 sentences in their native language (Korean), not English.

What did you try to make it work?:

I’ve downloaded some codes from GitHub (I don’t remember the user’s name) and the text input thing seems to work fine. But input-language changing which should be done with Caps Lock key is not working properly. The codes are below:

# ------Prepare to start Routine "ITV_input"-------
# update component parameters for each repeat
modify = False
text_ITV_input.text = ''
event.clearEvents('keyboard')
# keep track of which components have finished
ITV_inputComponents = [text_ITV_question, text_ITV_input]
for thisComponent in ITV_inputComponents:
    thisComponent.tStart = None
    thisComponent.tStop = None
    thisComponent.tStartRefresh = None
    thisComponent.tStopRefresh = None
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED
# reset timers
t = 0
_timeToFirstFrame = win.getFutureFlipTime(clock="now")
ITV_inputClock.reset(-_timeToFirstFrame)  # t0 is time of first possible flip
frameN = -1
continueRoutine = True

# -------Run Routine "ITV_input"-------
while continueRoutine:
    # get current time
    t = ITV_inputClock.getTime()
    tThisFlip = win.getFutureFlipTime(clock=ITV_inputClock)
    tThisFlipGlobal = win.getFutureFlipTime(clock=None)
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *text_ITV_question* updates
    if text_ITV_question.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
        # keep track of start time/frame for later
        text_ITV_question.frameNStart = frameN  # exact frame index
        text_ITV_question.tStart = t  # local t and not account for scr refresh
        text_ITV_question.tStartRefresh = tThisFlipGlobal  # on global time
        win.timeOnFlip(text_ITV_question, 'tStartRefresh')  # time at next scr refresh
        text_ITV_question.setAutoDraw(True)
    
    # *text_ITV_input* updates
    if text_ITV_input.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
        # keep track of start time/frame for later
        text_ITV_input.frameNStart = frameN  # exact frame index
        text_ITV_input.tStart = t  # local t and not account for scr refresh
        text_ITV_input.tStartRefresh = tThisFlipGlobal  # on global time
        win.timeOnFlip(text_ITV_input, 'tStartRefresh')  # time at next scr refresh
        text_ITV_input.setAutoDraw(True)
    keys = event.getKeys()
    if len(keys):
        if 'space' in keys:
            text_ITV_input.text = text_ITV_input.text + ' '
        elif 'backspace' in keys:
            text_ITV_input.text = text_ITV_input.text[:-1]
        elif 'lshift' in keys or 'rshift' in keys:
            modify = True
        elif 'return' in keys:
            text_ITV_input.text = text_ITV_input.text + '\n'
        elif 'lshift' in keys and 'return' in keys:
            continueRoutine = False
        else:
            if modify:
                text_ITV_input.text = text_ITV_input.text + keys[0].upper()
                modify = False
            else:
                text_ITV_input.text = text_ITV_input.text + keys[0]
    
    # check for quit (typically the Esc key)
    if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
        core.quit()
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in ITV_inputComponents:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()

# -------Ending Routine "ITV_input"-------
for thisComponent in ITV_inputComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
thisExp.addData('text_ITV_question.started', text_ITV_question.tStartRefresh)
thisExp.addData('text_ITV_question.stopped', text_ITV_question.tStopRefresh)
thisExp.addData('text_ITV_input.started', text_ITV_input.tStartRefresh)
thisExp.addData('text_ITV_input.stopped', text_ITV_input.tStopRefresh)
thisExp.addData("typedWord", text_ITV_input.text)
# the Routine "ITV_input" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()

What specifically went wrong when you tried that?:
When I pressed the Caps Lock key, it wouldn’t change the language of input but the words ‘Caps Lock’ were shown on the screen. Same thing happened when I pressed another functional keys such as Ctrl, Shift, etc. Is there anything that I can do to use the keys functionally in my experiment? I’m using Mac, but my potential participants may use Windows also.

Hi @Jeeyoung_Jeon, take a look at the text input demo here:

https://pavlovia.org/run/demos/textinput/html/

The code components deal with left and right shift, and can be adapted to use caps lock as well.

Thanks @dvbridges! I think this is the code that I used. So, do I have to put Caps Lock and Ctrl in here?

        elif 'lshift' in keys or 'rshift' in keys:
            modify = True

I also want to end the routine when left shift and Enter key were pressed simultaneously, so I put this line, but it doesn’t work.

        elif 'lshift' in keys and 'return' in keys:
            continueRoutine = False

How could I fix this? Thank you in advance!