How to detect whether if a key is being pressed down?

I want to have a code component under each frame, when I hold down the right-left arrow keys it will increment/decrement a variable. This will be used to rotate a line real time. At my current setup you need to constantly press and release, I want to make it so that as long as I hold down the key, the orientation will be updated. By the way, I’d appreciate a method which would also work online.

keys = event.getKeys(keyList=['left','right'])

if 'left' in keys:
    rot_line.ori += 2.0
elif 'right' in keys:
    rot_line.ori -= 2.0

The event module can’t give you information about when a key is held down or released, only when it is initially pressed. So you need to shift to the newer Keyboard class:

https://www.psychopy.org/api/hardware/keyboard.html

Thanks Michael.

I tried this under each frame:

kb = keyboard.Keyboard()
kb.clock.reset()
keys = kb.getKeys(['a', 'd'], waitRelease=False)

for thisKey in keys:
    if thisKey == 'a' and thisKey.duration == None:
        rot_line.ori += 2.0
    elif thisKey =='d' and thisKey.duration == None:
        rot_line.ori -= 2.0

I want it so that it rotates “rot_line” as long as I hold down a or d. However, right now I need to press and release it.

What is the solution to this?

Anyone who knows a solution? I would appreciate any help.

Sorry for the delay, I lost track of this thread.

You are re-creating and resetting the keyboard object on every frame, which will really muck with trying to detect if a key has been pressed before. Instead, this code should be in the “Begin routine” tab (so that it only happens once per trial), rather than in the “Each frame” tab (so that it gets run over and over, at typically 60 Hz):

kb = keyboard.Keyboard()
# this is likely not even necessary, as I guess it 
# is set to zero when the keyboard is created:
kb.clock.reset()

In terms of the rest of the code, I’m not too familiar with the Keyboard object, but I think you should set clear = False in the call to .getKeys(), or else you’ll have to keep pressing the key to have it be detected again.

No worries Michael. Thanks for helping.

Unfortunately that didn’t work either. Under begin routine:

kb = keyboard.Keyboard()
keys = kb.getKeys(['a', 'd'], waitRelease = False, clear=False)

for thisKey in keys:
    if thisKey == 'a':
        rot_line.ori += 2.0
    elif thisKey =='d':
        rot_line.ori -= 2.0

I will tag @jon now because I’m stuck and I really need to get this done soon :slight_smile:

Sorry for bothering Jon. Can you help me out please?

You can’t put all of that code in the “Begin routine” tab: it means that the keyboard will be checked only once per trial, before the trial even starts.

As stated above, only this should be in the “Begin routine” tab:

kb = keyboard.Keyboard()

Everything else should be in the “Each frame” tab, so that it runs on every screen refresh.

Ahh sorry I misunderstood you. Yeah this works fine, thank you.

Hi Michael. How can I get this working online? The keyboard class isn’t loaded by default from what I see. So how can I import it online?

Sorry, I’m not that familiar with the JavaScript side of things. Might be a question for @wakecarter

Sorry. I haven’t yet managed to get the new keyboard class working online.

However, according to @dvbridges you need to manually translate the Python code

kb = keyboard.Keyboard()

to JavaScript

kb = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true}); 
2 Likes

I tried this beforehand (since I follow the cribsheet) and it didn’t work. Shall I ask @dvbridges ? Maybe he knows the exact way.

Does anybody know how can I detect key combinations using the keyboard class?

Such as pressing Y and N at the same time, or holding down Y and pressing N at the same time, or visa-versa.

@dvbridges

Hello David, do you have a solution to this problem?

ie. How do I get the keyboard class working online?


2021 EDIT: For newer versions of PsychoPy, please use the Python code provided here for offline experiments: Failure to detect pressed key - #8 by sol


After looking at the generated .js files and the source code of the PsychoJS library, I figured out how to do this.

All code is javascript.

begin experiment

m_rot_kb = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true});
key_list = [];
key_name = "";

begin routine

m_rot_kb.clock.reset();
m_rot_kb.start();
m_rot_kb.clearEvents();

each frame:

let keys_obj = m_rot_kb.getKeys({keyList: ["left", "right"], waitRelease: false, clear: false});

key_list = key_list.concat(keys_obj);
if (key_list.length > 0) 
{
    key_name = key_list[key_list.length - 1].name;
    key_duration = key_list[key_list.length - 1].duration;
    //console.log(key_name);
    //console.log(key_duration);
    if(key_name === "right" && key_duration == undefined)
    {
         console.log("right");
    }
    else if(key_name === "left" && key_duration == undefined)
    {
         console.log("left");
    }
}

end routine

m_rot_kb.clock.reset();
m_rot_kb.stop();
m_rot_kb.clearEvents();
2 Likes