OS (e.g. Win10): MacOS, Win7 PsychoPy version (e.g. 1.84.x): 3.0.0
**Standard Standalone? Yes
**What are you trying to achieve?:I would like to change the keypress to end an experiment from escape to another key, such as ctrl+escape. I am having my participants enter numbers to respond to stimuli and have had problems where they accidentally hit escape when trying to press 1.
**What did you try to make it work?: I tried to enter Coder view and replace escape with ctrl+escape.
**What specifically went wrong when you tried that?:PsychoPy will not respond to ctrl+escape or escape when I am in the experiment and am forced to ctrl+alt+del to end PsychoPy
Hi @eyexciteme, to disable the escape key, go to your experiment settings, and deselect the Enable escape key option. In PsychoPy, once you have disabled the escape key, you cannot reuse it in combination with other keys. Instead, you could use another common key combination. Choose your combination of keys to quit the experiment, add a code component, and in the Every Frame tab:
keys = event.getKeys()
for key in keys:
if âctrlâ in key and âzâ in key:
core.quit()
Weâve tried this solution with no luck. If I understand correctly, this snippet should be put in every routine in code components on the âeach frameâ tab.
I have tried multiple combination of keys, and the experiment quits when I input any three keys (regardless of timing). For example, if I press spacebar to advance past the two routines, then after the third spacebar, the experiment will quit.
Iâve tried naming all the âkeysâ objects differently. Iâve also tried just putting this code in one routine. Then, the experiment doesnât close like above, but I also canât close the experiment unless Iâm in that one routine.
Thanks. That sort-of works. If I put that code in the âbegin routineâ tab for each routine, and I press those two buttons, it wonât quit immediately, but it will quit when that routine finishes. A workable fix, I suppose.
ie putting a for loop in there will break things, as you want to check that both keys are in the entire list, rather than iterate over individual items, which by definition canât have two entries.
I can confirm that this doesnât work, unfortunately. Iâm assuming if keys gets created every frame, it wonât quit unless âbâ and âpâ are input on the same frame. The best workaround Iâve found is creating keys in âBegin Routineâ and then looking for âbâ and âpâ each frame. However, this still only quits at the end of the routine.
edit: pressing them simultaneously works
Yeah, that code above has been crossed out. If youâre just looking Python-only fix that uses key modifiers in combination with normal characters, try the following in the Each Frame tab, which will cause experiment to quit using âctrlâ and âdâ:
keys = event.getKeys(modifiers=True)
if len(keys):
key = keys[-1]
if key[0] == 'd' and key[1]['ctrl']:
core.quit()
The other solution with the new keyboard involves storing all keypresses and clearing them if they are not they keys you want. In your case above you want to participant to press âbâ and âpâ. E.g.,
# Start exp
kb = keyboard.Keyboard()
# Each Frame
keys = kb.getKeys(clear=False)
if len(keys) > 1:
if keys[0].name == "b" and keys[1].name == "p" or keys[0].name == "p" and keys[1].name == "b":
core.quit()
else:
kb.clearEvents()
Are you sure my code doesnât work for simultaneous key presses (which is what I assumed you wanted).
Alternatives could be appending new key presses to a list each frame and then checking whether the two keys are in that list, or resetting a timer when one key is pressed and then ending the routine if the other key is pressed within a certain time.
This iohub based solution could also be an option, and both keys do not need to be initially pressed within the same frame:
At start of experiment:
from psychopy.iohub import launchHubServer
# Start iohub and get the keyboard device
io_keyboard = launchHubServer().devices.keyboard
on each frame, when you want to check if âleft-controlâ and âcâ are currently pressed:
if 'lctrl' in io_keyboard.state and 'c' in keyboard.state:
print("exiting....")
core.quit()
Hereâs a complete python example that checks for lctrl+c for 10 seconds:
from psychopy import iohub, core
keyboard = iohub.launchHubServer().devices.keyboard
print("Press lctrl + c...")
stime = core.getTime()
while core.getTime() - stime < 10:
if 'lctrl' in keyboard.state and 'c' in keyboard.state:
print("lctrl + c are pressed")
core.quit()
print("Timeout")