Display keyboard number presses

hi all, i would like to take keyboard number presses and display them on the screen. participants can press any number between 1-100, then press enter to move to the next trial. i can only get it to display the previous number (theseKeys[-1]) or all the numbers (theseKeys) in the form [‘8’ ‘5’ ‘return’]. I would like to simply display the number itself (85, without ‘enter’) and i would also like to store this number for use in the next trial.

some example of my script is below.
thank you

            theseKeys3 = event.getKeys(keyList=['1','2','3','4','5','6','7','8','9','0', 'return'])
         
            if len(theseKeys3) >0:  # at least one key was pressed
                key_resp_3.keys.extend(theseKeys3)  # storing all keys

            #if len(theseKeys3) ==1:
               choicetext.setText(theseKeys3[-1])

            if "return" in theseKeys3:
                continueRoutine=False

I tried using things like:

if len(theseKeys3) ==2:
choicetext.setText(theseKeys[-1],theseKeys[-2])

etc but this doesn’t work

The following might work:

theseKeys3 = event.getKeys(keyList=['1','2','3','4','5','6','7','8','9','0', 'return'])

key_resp_3.keys.extend([key for key in theseKeys3 if key != "return"])

choicetext.setText("".join(key_resp_3.keys))

if "return" in theseKeys3:
    continueRoutine=False
1 Like

thank you so much- that worked. if you have a moment could you explain this part:

[key for key in theseKeys3 if key != “return”]

I am trying to save the number as an integer for my record and also for use in the next trial. I’ve tested it with print key_resp_3.keys / key / theseKeys3 / join(key_resp_3.keys) etc and cannot record the integer. any thoughts?

thanks again,
Laurel

Hi Laurel,

Sure. That is a ‘list comprehension’, and is a short way of doing the following:

keys = []
for key in theseKeys3:
    if key != "return":
        keys.append(key)

If you want to save it as an integer, you need to convert the list of strings contained in key_resp_3.keys:

# convert the list of strings into a single string
key_str = "".join(key_resp_3.keys)
# then convert the string to a number
key_num = int(key_str)
2 Likes

thank you so much djmannion, that works perfectly.
I have now added a backspace to the task too, to let the participant delete mistakes (in case anyone watching out there needs to do this too).

Laurel

            theseKeys3 = event.getKeys(keyList=['1','2','3','4','5','6','7','8','9','0', 'return', 'backspace'])
            
            # check for quit:
            if "escape" in theseKeys3:
                endExpNow = True
                
            if len(theseKeys3) >0:  # at least one key was pressed
                #key_resp_3.keys.extend(theseKeys3)  # storing all keys
                if "backspace" in theseKeys3:
                    key_resp_3.keys=key_resp_3.keys[:-1]
                    
                key_resp_3.keys.extend([key for key in theseKeys3 if key != "return" and key != "backspace"])
                choicetext.setText("".join(key_resp_3.keys))
                
                # convert the list of strings into a single string
                key_str = "".join(key_resp_3.keys)
                
                if len(key_str) !=0:
                # then convert the string to a number
                    key_num = int(key_str)

            if "return" in theseKeys3:
                choicetext.setText('')
                continueRoutine=False

Hi,
What is "key_resp_3’ here? I am trying to use coder doing similar things here. But I don’t know how to initialize ‘key_resp_3’. I tried both empty dictionary and key_resp_3 = event.BuilderKeyResponse(). Nether of them works.

@Miao, you can either create a keyboard object, or use the events module. If you want to use the event module, see Writen response for an idea of what to do.

Thank you for your reply. I went through all the relative links and came up with several lines in the code component in the builder. Want I want to do in a single trial is that show an image to participant and display their response on the next display, and their response will be only numbers between 1-999.

keys = event.getKeys(keyList = ['1','2','3','4','5','6','7','8','9','0','return','backspace'])
if 'escape' in keys:
    endExpNow = True
else:
    if len(keys) > 0:
        #allow backspace for editing
        if 'backspace' in keys:
            key_resp_3.keys = key_resp_3.keys[:-1]
        #store pressed numbers
        key_resp_3.keys.extend([key for key in keys if key != 'return' and key!= 'backspace'])
        key_str = ''.join(key_resp_3.keys)
        key_num = int(key_str)
        #present numbers on screen
        displayText.setText(key_num)
        #displayText.draw()
        #win.flip()
        #core.wait(2)
    else:
        displayText.setText('missing response')
        #displayText.draw()
        #win.flip()
        #core.wait(2)

If I understand correctly, if I create a text component in builder, I don’t need to define anything like text = visual.TextStim(win), nor text.draw() stuff. But I still cannot present the number input.

My other question is that: how does psychopy know when its the end of participants input when I use builder.
Usually, in the coder, I would write something like
message = visual.TextStim(win)
message.setText =(‘enter your reponse’)
message.draw()
win.flip()
core.wait(5)
keys = event.getKeys()
So, within the 5sconds, psychopy will recond all the key response.
But what I actually want to do is not to set a time limit. Only participant press a certain key, say ‘space’ or ‘return’ , then continue next trial. How can I do the same thing by builder?

I also attached my builder component below.
Could you kindly help me with my questions?

Thank you so much in advance.