psychopy.org | Reference | Downloads | Github

Wait for mouse clicks

Hi everyone,

my current experiment requires the use of the left and right mouse button as response keys, because the participants need to respond in different postures (sitting, standing, and lying down). The mouse can be put in their hands more easily than the keyboard.

Basically, all I need to do for that is to record the press of the left and right mouse button the same way I’d record e.g. pressing “V” and “M” as response keys - to record their timing and accuracy (correct / false response). Pretty standard stuff, one would think.

However, as far as I know, there is no option of waiting for mouse clicks in PsychoPy?

  • event.waitKeys() allows to wait for keypresses on the keyboard, but not on the mouse
  • mouse.getPressed() allows to register whether a mouse key is currently being pressed, but does not make the core wait for the press
  • using core.wait() and hogCPU for the entire time of the wait allows for registering mouse button presses during the wait, but will not interrupt the wait once the click occurs; if for example you set the waiting duration to 5 seconds, you will have to wait for the entire 5 seconds to pass even after having clicked
  • I read about a function of the core.Clock() called clock.getSecs() - someone was using “while clock.getSecs() < 3”, followed by event.getKeys() and mouse.getPressed(), but PsychoPy tells me “Clock” had no attribute called “getSecs”

At my institute the preceding study using this paradigm was conducted using Experiment Builder, which is also in Python, but this also means no one there has a template for waiting for mouse clicks in PsychoPy based on previous research. :frowning:

Are you wanting to use PsychoPy Builder or Coder?

I work in the coder view, that’s why I posted this in “Coding” :wink: .

But anyways, I was able to solve the issue in the meantime thanks to the help of another employee at the institute:

We now use a while-loop to halt PsychoPy and continuously check for mouse clicks. So we made the condition “while buttons == (0, 0, 0): mouse.getPressed()”. Meaning: As long as no mouse button is being pressed, PsychoPy constantly keeps checking for mouse clicks. And then, “if buttons == (1, 0, 0) or buttons == (0, 0, 1): break”, i.e. in case of a left or right click, the while loop is interrupted.

The downside is that we can’t seem to combine this with event.waitKeys(), so that it is not possible to enable the option of quitting the experiment on every single trial, by pressing e.g. escape. Because whenever I put both mouse.getPressed() and event.getKeys() inside the while loop, logically, both are being executed in constant rapid, alternating succession.

Hi @Strato_Incendus,
I am having the same problem. Is it possible that you can give me a small example with ‘while buttons == (0, 0, 0): mouse.getPressed()’? That would be a great help.
In my case, I want to switch the solenoid valves if there is a click on the tick mark of the rating scale. For ex: If I click on 0 tick mark of the rating scale one solenoid valve will be switch on and if I click on the 1 tick mark of the rating scale another solenoid valve will be on.

Sure, I’m glad if I can help, for a change! ^^ So far I’ve usually been the one asking for it…

Here in the entire context of an auditory task that required either a left right mouse click as a response.

At the beginning, set up the mouse:

myMouse = event.Mouse(visible = False, win = win)

Then, this is what happens from stimulus onset on:

    stimulus.play()
    trial_clock.reset()
    myMouse.clickReset()
    event.clearEvents() #get rid of other, unprocessed events
    buttons, times = myMouse.getPressed(getTime = True)
    while buttons == [0, 0, 0]:
        buttons, times = myMouse.getPressed(getTime = True)
        trialdur = trial_clock.getTime()
        if buttons == [1, 0, 0] or buttons == [0, 0, 1]:
            break
        elif trialdur > waittime: # if subject takes too long to respond
            break
            times = myMouse.clickReset()
    stimulus.stop()
    if times[0] > 0:
        response = "left"
        rt = times[0]
    elif times[2] > 0:
        response = "right"
        rt = times[2]
    elif times == [0.0, 0.0, 0.0]:
        response = "none" # to prevent PsychoPy from registering the response from the previous trial in a trial where no response is given
        rt = "none" # to prevent PsychoPy from registering the RT from the previous trial in a trial where no response is given
        print "too slow!"
        tone_error.play()
    print response
    print rt
    times = myMouse.clickReset()
    event.clearEvents() #get rid of other, unprocessed events

For what you describe, I hear you need a visible mouse, so obviously you’d need to set this to “True” when setting up the mouse. :wink:

Then you can easily check the position with “if myMouse.isPressedIn(<name_of_visual_stimulus>)”. :slight_smile:

Thanks for the advice. Meanwhile I came up with this solution and it is working for me. Since, the return value of mouse.getPressed () is a list [0,1,2] of the left, middle and right button. It is possible to access individual via mouse.getPressed () [0] means left button etc. Here is the code for your reference. :wink:

while (timer.getTime() > 0): 
           
            myRatingScale12.draw()
            win.flip()
            rating12 = myRatingScale12.getRating()
            myMouse = event.Mouse()
            mouse_dX, mouse_dY = myMouse.getRel()
            if rating12 == 0:
                while (myMouse.getPressed()[0] != 1):
                    if  u'i' in event.getKeys(keyList = ['i']):
                        command = arduino.write(struct.pack(u'>H',513)) 
                        myBreathingCycles = myBreathingCycles - 1
                        
                    if  u'e' in event.getKeys(keyList = ['e']):
                         command = arduino.write(struct.pack(u'>H',512))
                         myBreathingCycles = myBreathingCycles - 1
                            
                    myRatingScale12.reset()