When key press do one thing, when key hold do something else

152 views
Skip to first unread message

CamillaM...@hotmail.com

unread,
Feb 25, 2022, 7:37:24 AM2/25/22
to pyglet-users
Hi, 

I am trying to code a rating scale where the marker moves one pixel when a key is pressed, but if the user holds the key down, the marker should move continuously until the key is released. Any ideas on how to do that? In the below code, VAS is a psychopy ratingScale object. 

############################ # Pakages # ############################
from psychopy.hardware import keyboard as kb
from psychopy import visual, event
import pyglet
from pyglet.window import key as PygKey

############################ # Set up window # ############################
win = visual.Window(size=[800, 800],        # Screen size
                    units="pix",            # The size and placement of stimuli is defined in pixels
                    monitor = "Monitor",    # Monitor can be set to 1 or 2
                    fullscr=False,          # Full Screen True or False
                    color=[0, 0, 0])        # Color of the background in the window  
                                            # [1,1,1] = White, [0,0,0] = Grey, [-1,-1,-1] = black


############################ # Set up pyglet # ############################
pyglet_keyboard=pyglet.window.key
keyboard = pyglet_keyboard.KeyStateHandler()
kb = kb.Keyboard()
win.winHandle.push_handlers(keyboard)
PygKeys = PygKey.KeyStateHandler()

############################ # Set up rating scale # ############################

increment = 0.5                               # How fast the marker moves via button hold
SmallIncrement = 1                        # How far the button moves from quick press
High = 100                                  # The max number on the scale
Low = 0                                     # The min number on the scale
Window = win                                # The window the rating scaled is placed in
MarkerStart = 50                    
       # Marker starting point

VAS = visual.RatingScale(win=Window,        
low = Low,
high = High,
marker = 'triangle',
markerColor  = 'Black',
markerStart  = MarkerStart,
lineColor = 'black',
tickMarks = [0,100],
stretch = 1.5,
noMouse = True,
leftKeys  = 'left',
rightKeys = 'right',
showAccept = False,
tickHeight = 1.5,
acceptKeys = 'space',
textColor = 'Black')

rating_value= None
event.clearEvents()
#for frameN in range(10000):
while VAS.noResponse:
    if PygKeys[PygKey.RIGHT]:
        VAS.markerPlacedAt += increment
    #if keyboard[pyglet_keyboard.RIGHT]:
        #VAS.markerPlacedAt += SmallIncrement
    if PygKeys[PygKey.LEFT]:
        VAS.markerPlacedAt -= increment
    #if keyboard[pyglet_keyboard.LEFT]:
        #VAS.markerPlacedAt -= SmallIncrement
    if VAS.markerPlacedAt > High:
        VAS.markerPlacedAt = High # do not allow marker to move outside the scale (above 100)
    elif VAS.markerPlacedAt < Low:
        VAS.markerPlacedAt = Low # do not allow marker to move outside the scale (below 0)
    VAS.draw()
    win.flip()
    rating_value = VAS.getRating()
win.close()

If I comment out the elif statements, the marker moves in small increments. If I instead comment out the if statements (and change the elifs to ifs) the marker moves continuously, When I do not uncomment any lines, the marker moves continuously as well. Any help or advise would be greatly appreciated

Darth Dan

unread,
Mar 3, 2022, 5:11:41 PM3/3/22
to pyglet-users
I am not seeing any sort of timing function involved (which would be necessary if you want any control over your cursor movement beyond the standard windows key repeat). I'd suggest looking into https://pyglet.readthedocs.io/en/latest/programming_guide/time.html , namely the schedule_interval option.

Currently your code is trying to repeat the inputs as fast as possible, so you likely have next to no control over where it'll stop or how far it'll go when you tap the key. I would suggest implementing the shedule_interval and proceeding with:

if PygKeys[PygKey.RIGHT]:
if right_pressed == 0:
VAS.markerPlacedAt += increment
elif right_pressed > MIN_HOLD_TIME:
VAS.markerPlacedAt += increment
right_pressed += 1
elif !PygKeys[PygKey.RIGHT]:
right_pressed = 0

This makes your marker only offset by increment only once if you tap the key shorter than the MIN_HOLD_TIME, and increment it continuously once you're holding it longer than that. Can even use different increments. The elif makes sure that once the key is released, the key_pressed variable is reset to 0, so if you rapidly tap it (a sequence of pressed and released events), you should be able to get rapid precision movement. I'd still adivse using the on_key_press and on_key_release events themselves over the KeyStateHandler() class for more control, though, but that might be just my preference.

Reply all
Reply to author
Forward
0 new messages