How to detect asynchronously whether a key is pressed?

I am trying to fade a grating continuously while a key is held down.

I have the following in Each Frame:

key = event.getKeys()
if key:
    print(key)
    print(c)
    c = c - 0.01
    grating.contrast = c
    print(grating.contrast)

However, only one keypress is registered, nothing further happens while the key is held down.

Could I ask for some help understanding this? I thought that getKeys would check asychronously whether a key was down. However, it doesn’t register another keypress until I release the key and press it again.

I also tried:

key = kb.getKeys(['right'], waitRelease=False)

However the same behaviour occurred.

After reviewing some similar threads, I also tried

keys = kb.getKeys(['right'], waitRelease=False, clear=False)
keys2 = kb.getKeys(['right'], waitRelease=True, clear=True)

however, this leads to the grating fading all the way as soon as a key is pressed and released (I suppose because the key event is not cleared and keeps firing on every frame).

Am I missing something here?

Hello.

Here is an example Visual analog scale: press and hold key that might help. https://discourse.psychopy.org/uploads/short-url/vhjN53gpBka8L0xw1GGZsYf0py.psyexp. There is also an example in the demo experiments that works in a similar way.

Best wishes, Jens

I’ve just written a demo for this which might be useful

Key Down code | try it

Compares the length of two keyboard components (one detecting key presses and the other key releases) to determine whether a key is currently pressed down.

The right way to look at this is that GetKeys simply tells you what keyboard events (presses or releases) are in the keyboard buffer - it is up to you to track whether keys are actually up or down in Every Frame:

keys = mykb.getKeys(keysWatched, waitRelease = False, clear = False)

if len(keys):# if a key has been pressed
    print(keys)
    for k in keys:
        print(k.name)
    for i, key in enumerate(keysWatched):
        if keys[-1].name == 'left':
            if keys[-1].duration:
                left_down = False
            else:
                left_down = True
        if keys[-1].name == 'right':
            if keys[-1].duration:
                right_down = False
            else:
                right_down = True

if left_down:
    contrast -= 0.1
    grating.contrast = contrast
    
if right_down:
    contrast += 0.1
    grating.contrast = contrast

and in Begin Routine:

contrast = 1

mykb = keyboard.Keyboard()
left_down = False
right_down = False


keysWatched=['left', 'right']

status =['up']

1 Like