Search code examples
matlabmousepsychtoolbox

Using GetMouse/GetClick to get location of a click in psychtoolbox


I'm trying to get the x,y coordinates of a click using Psychtoolbox on Matlab. My program needs to do the following things: 1. Place a dot where the user clicks. 2. Store the x,y location of the this click and all subsequent clicks in a single array. 3. Finally, the program should exit when a keyboard press is detected.

This is the code I have for this program:

clear all;
%Set up a full screen with cursor
Screen('Preference', 'SkipSyncTests', 2);
[EXPWIN, scr_rect] = Screen('OpenWindow', 1);
ShowCursor('CrossHair', EXPWIN);
%General variable setup 
clicks = 0;
black = [1,0,0];
nchunk = 1; % Chunk number
%main loop
while ~KbCheck %check keyboard has not been pressed
    [nclicks, mousx, mousy, buttons] =GetClicks(EXPWIN, 0); %Click loc
    %[mousx, mousy, buttons] =GetMouse(EXPWIN); %alternate click loc
    if any(buttons)
        clicks = clicks+1
        [x,y] = GetMouse;
            aoi_corners(nchunk, clicks)= x;
            aoi_corners(nchunk, clicks+1)= y;
            Screen('DrawDots', EXPWIN, [x, y], [10], black)
            Screen('Flip', EXPWIN, 0, 1) 
    end
end
sca; 

The problem is essentially that, if I use getclicks to get the x,y coordinates I can get good x,y coordinates for the dot in my aoi_corners matrix as it takes the x,y at the point of button release. However it stops KbCheck from working (my searches tell me this is because it operates like KbCheck and pauses the program while it waits for more clicks?).

Using getmouse on the other hand, allows KbCheck to work but takes the x,y coordinates from the point of the button getting pressed down, so it returns loads of values I don't need, even if I press and release the button as fast as I can.

My question is then is how do I get around this? Have I missed something obvious/written my code badly?

thanks for your help,

Martin


Solution

  • The issue with GetClicks is that the keyboard is not being checked while waiting for the click, as you noted. But for example holding a key as you click the mouse will break out of the loop.

    If you instead use GetMouse, but also wait until the button has been released before moving on, I think you'll get the behavior you want. Another thing I noticed, which wasn't in your original question, is that on each click you're iterating the click variable by 1, but you're saving the X and Y position to click, and click + 1. In this case click 1 X and Y will be in positions 1 and 2, but click 2 X and Y will be in positions 2 and 3, so the Y from the first click will be overwritten by the X from the second click, etc. In my example I instead save X and Y to the third dimension of aoi_corners.

    clear all;
    %Set up a full screen with cursor
    Screen('Preference', 'SkipSyncTests', 2);
    [EXPWIN, scr_rect] = Screen('OpenWindow', 1);
    ShowCursor('CrossHair', EXPWIN);
    %General variable setup
    clicks = 0;
    black = [1,0,0];
    nchunk = 1; % Chunk number
      %main loop
    while ~KbCheck %check keyboard has not been pressed
        [x, y, buttons] =GetMouse(EXPWIN); %alternate click loc
        if any(buttons)
            clicks = clicks+1;
            aoi_corners(nchunk, clicks, 1)= x;
            aoi_corners(nchunk, clicks, 2)= y;
            Screen('DrawDots', EXPWIN, [x, y], [10], black)
            Screen('Flip', EXPWIN, 0, 1)
            % wait until the mouse is released
            while(any(buttons))
                [~, ~, buttons] =GetMouse(EXPWIN);
               WaitSecs(.001); % wait 1 ms 
            end
        end  
    end
    sca;