Restricting allowed keys in textbox component

I am using the last version of PsychoPy (2021.1.4) for Windows and quite new to psychopy.
My goal is to create distractor task by using various mathematical questions. To do this I need to get keyboard responses from participant. I find textbox component to easiest way to do this. I have several questions regarding textbox:

  1. How to restrict the keys participants can press in textbox? I tried using keyboard component to do this but it did not work.
  2. How to limit the distractor task’s duration ? eg. 15 secs

Thank you in advance

The easiest way is to use a Keyboard :keyboard: component and a Code :code: component - in the Each Frame tab of the code component, add something like:

# what keys have been pressed this frame?
keys = keyboard.getKeys()
# if any, check that they're the right keys
if keys:
    if keys[-1] not in correctKeys:
        # if they're not valid, remove the last inputted character from the textbox
        myTextBox.text = myTextBox.text[0:-1]

Alternatively, you could set editable to be False on the textbox and use similar code to add the key if valid

1 Like

Thanks a lot! I tried the solution but had attribute error, I am pasting the error below:

keys = keyboard.getKeys()
AttributeError: module ‘psychopy.hardware.keyboard’ has no attribute ‘getKeys’

Sorry, I should have been clearer, in this case keyboard should be replaced with the name of your keyboard :keyboard: component

Thanks! that had solved most of my problems!

Thank you, this is very helpful!

Hi,

I am trying to do something related to this, and simply disallow participants from typing ‘return’ (as in to make a line break in the textbox) - in other words I want it so every key is allowed apart from return - if they press return I do not want a line break to be made. I’ve tried variations on your code such as setting up the keyboard component to accept all keys and replacing:

if keys[-1] not in correctKeys:

with

if keys[-1] == ‘return’:

…but it had no effect. No error but also no effect. Any suggestions? Thanks!

Hello

it is better to open a new post and adding to a post that has been marked as a solution.

Does the following to the trick four you? Put this in the Tab Each frame and have the code-component in the top row.

keys = key_resp.getKeys()

if keys:
    if ('return' in keys):
        textbox.text = textbox.text[0:-1]

Notice that I have used the “standard” name key_resp for the keyboard-component and textbox for the textbox-component. You might want to change that to your setup.

Best wishes Jens

Hi Jens,

Thank you, potentially the problem was that it wasn’t on the top row! Since it was ‘each frame’ I didn’t think it would make a difference what row the code component was on.

Best wishes,
Michael

EDIT However, @JensBoelte it does not work when running online on Pavlovia - possibly expected since the auto > JS code looks very bizarre. If anyone can tell me what is going on here I’ll be grateful:

var _pj;
function _pj_snippets(container) {
function in_es6(left, right) {
if (((right instanceof Array) || ((typeof right) === “string”))) {
return (right.indexOf(left) > (- 1));
} else {
if (((right instanceof Map) || (right instanceof Set) || (right instanceof WeakMap) || (right instanceof WeakSet))) {
return right.has(left);
} else {
return (left in right);
}
}
}
container[“in_es6”] = in_es6;
return container;
}
_pj = {};
_pj_snippets(_pj);
keys = Sb_Trial_keyboard.getKeys();
if (keys) {
if (_pj.in_es6(“return”, keys)) {
Sb_Trial_box.text = Sb_Trial_box.text.slice(0, (- 1));
}
}

Hello

Yesterday I did not try the code in a browser, and while the code does not throw an error, it also does not “ignore” return in the input. One reason could be that the “return” key is called Enter in JavaScript. However, changing return to Enter as I did below did not give the desired behaviour of ignoring “enter”. I assume that the if-construction is not true and therefore Enter is not removed from the input. However, my JavaScript is too bad to help you here.

By the way, enclose your code in triple `, then it will be formatted correctly.

var _pj;
function _pj_snippets(container) {
    function in_es6(left, right) {
        if (((right instanceof Array) || ((typeof right) === "string"))) {
            return (right.indexOf(left) > (- 1));
        } else {
            if (((right instanceof Map) || (right instanceof Set) || (right instanceof WeakMap) || (right instanceof WeakSet))) {
                return right.has(left);
            } else {
                return (left in right);
            }
        }
    }
    container["in_es6"] = in_es6;
    return container;
}
_pj = {};
_pj_snippets(_pj);
keys = key_resp.getKeys();
if (keys) {
    if (_pj.in_es6("Enter", keys)) {
        textbox.text = textbox.text.slice(0, (- 1));
    }
}

Best wishes Jens

1 Like