Mouse cursor limits

480 views
Skip to first unread message

Michele M.

unread,
Apr 5, 2011, 10:44:28 AM4/5/11
to psychop...@googlegroups.com

Hi all,


I'm new to Psycopy, i'm trying to figure out how to limit mouse cursor movement inside a box. In E-Prime i use the method MouseDevice.SetCursorLimits ( see the bottom for description extracted from E-Prime Help).
I have no idea how to achieve the same result in Psycopy. Thank in advance helping

Michele M.
-----

MouseDevice.SetCursorLimits (method)

Syntax

MouseDevice.SetCursorLimits leftLimit, topLimit, rightLimit, bottomLimit

Description

  Restrict the area in which the mouse cursor can be moved to the rectangle defined by leftLimit, topLimit, rightLimit, bottomLimit.

Comments

  • leftLimit, topLimit, rightLimit, bottomLimit are of type long

  • Valid values for leftLimit, topLimit, rightLimit, and bottomLimit are longs or variables of type long

  • When the mouse device is opened, the mouse cursor limits are initialized to the full screen.

  • To retrieve the current mouse cursor limits, use MouseDevice.GetCursorLimits

----

Rebecca Sharman

unread,
Apr 5, 2011, 11:10:05 AM4/5/11
to psychop...@googlegroups.com
Hi,
 
I don't think there's anything like that built into Psychopy at the moment, but how about something like this as a starting point i.e. creating some loops to reposition the pointer if
it strays out of the windowed area:
 
 
but using event.mouse (http://www.psychopy.org/api/event.html) rather than Rasterizer?
 
I haven't tried this myself so I don't know if the code that was published on that forum actually works properly, but I'm hoping that the principle is about right and it will give you a place
to start from :D
 
Becky
 

--
You received this message because you are subscribed to the Google Groups "psychopy-users" group.
To post to this group, send email to psychop...@googlegroups.com.
To unsubscribe from this group, send email to psychopy-user...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/psychopy-users?hl=en.

Gary Lupyan

unread,
Apr 5, 2011, 11:40:12 AM4/5/11
to psychop...@googlegroups.com
Just a heads up on this: I believe the function to set the mouse
position (setPos) only works in pygame not pyglet. So, constraining
the position of the mouse using setPos won't work in pyglet. An
alternative is to use a custom mouse cursor (e.g., an image of a mouse
pointer whose position is set by reading off the mouse position
event).
You can then "freeze" the position of this cursor if the mouse moves
outside a bounding box using the method mentioned on the page in
Becky's message.

More hassle then eprime to be sure, but once you write a function to
do this you can reuse it in all your scripts :)

-----------------------------------------------------
Gary Lupyan - lup...@wisc.edu
Assistant Professor of Psychology
University of Wisconsin, Madison
http://mywebspace.wisc.edu/lupyan/web/
-----------------------------------------------------

Jeremy Gray

unread,
Apr 6, 2011, 12:45:04 AM4/6/11
to psychop...@googlegroups.com
On Tue, Apr 5, 2011 at 11:40 AM, Gary Lupyan <glu...@gmail.com> wrote:
Just a heads up on this: I believe the function to set the mouse
position (setPos) only works in pygame not pyglet.  So, constraining
the position of the mouse using setPos won't work in pyglet.  An
alternative is to use a custom mouse cursor (e.g., an image of a mouse
pointer whose position is set by reading off the mouse position
event).
You can then "freeze" the position of this cursor if the mouse moves
outside a bounding box using the method mentioned on the page in
Becky's message.

More hassle then eprime to be sure, but once you write a function to
do this you can reuse it in all your scripts :)

I wrote a little class to provide a customizable mouse, including limits on movement. it has some rough edges but it does quite a lot, including working with pyglet (and probably pygame, not tested). it seems to work with pix or norm units.

hopefully you can just use it like you would an event.Mouse(). that's the idea but the implementation might be lacking, ideas or improvements are most welcome.

--Jeremy

------------------copy & paste below here------------------
#!/usr/bin/env python

# demo of CustomMouse()
# author Jeremy Gray

from psychopy import visual, event
import numpy

class CustomMouse():
    """Class for more control over the mouse, including the pointer graphic and a bounding box.
  
    Not well tested. Known limitations / bugs:
    - getRel() always returns [0,0], maybe that's ok
    - mouseMoved is always False, no idea why, seems bad
    - unsure if clickReset() does anything
    - resetting the limits does not always take effect fully
    """
    def __init__(self, win, newPos=None, visible=True,
                 leftLimit=None, topLimit=None, rightLimit=None, bottomLimit=None,
                 pointer=None):
        self.win = win
        self.mouse = event.Mouse(win=self.win)
        # partial Mouse.__init__
        self.lastPos = None
        self.prevPos = None
        self.getRel = self.mouse.getRel
        self.getWheelRel = self.mouse.getWheelRel
        self.mouseMoved = self.mouse.mouseMoved  # FAILS
        self.mouseMoveTime = self.mouse.mouseMoveTime
        self.getPressed = self.mouse.getPressed
        self.clickReset = self.mouse.clickReset  # ???
        self._pix2windowUnits = self.mouse._pix2windowUnits # ???
        self._windowUnits2pix = self.mouse._windowUnits2pix # ???
      
        # the graphic to use as the 'mouse' icon (pointer)
        if pointer:
            self.setPointer(pointer)
        else:
            self.pointer = visual.TextStim(win, text='+', height=.08)
        self.mouse.setVisible(False) # hide the system mouse
        self.visible = visible # the custom mouse
      
        if type(leftLimit) in [int,float]: self.leftLimit = leftLimit
        else: self.leftLimit = -1
        if type(rightLimit) in [int,float]: self.rightLimit = rightLimit
        else: self.rightLimit = 1
        if type(topLimit) in [int,float]: self.topLimit = topLimit
        else: self.topLimit = 1
        if type(bottomLimit) in [int,float]: self.bottomLimit = bottomLimit
        else: self.bottomLimit = -1
        if newPos is not None:
            self.x, self.y = newPos
        else:
            self.x = self.y = 0
    def setPos(self):
        self.pointer.setPos(self.getPos())
    def getPos(self):
        dx, dy = self.getRel()
        self.x = min(max(self.x+dx, self.leftLimit), self.rightLimit)
        self.y = min(max(self.y+dy, self.bottomLimit), self.topLimit)
        self.lastPos = numpy.array([self.x, self.y])
        return self.lastPos
    def draw(self):
        self.setPos()
        if self.visible:
            self.pointer.draw()
    def getVisible(self):
        return self.visible
    def setVisible(self, visible):
        self.visible = visible
    def setPointer(self, pointer):
        if 'draw' in dir(pointer) and 'setPos' in dir(pointer):
            self.pointer = pointer
        else:
            raise AttributeError, "need .draw() and setPos() methods in pointer for CustomMouse"

#    
#    end of the class, start of the demo:
#

myWin = visual.Window()
vm = CustomMouse(myWin, leftLimit=0, topLimit=0, rightLimit=0.3, bottomLimit=-0.3)
instr = visual.TextStim(myWin,text="move the mouse around\nclick to release the mouse bound")
new_pointer = visual.TextStim(myWin,text='o') # anything with .draw() and .setPos(), like PatchStim()

while not 'escape' in event.getKeys():
    instr.draw()
    vm.draw()
    myWin.flip()
    if vm.getPressed()[0]:
        #vm.setVisible(not vm.getVisible()) # click toggles mouse visibility via get/set
        print "[%.2f, %.2f]" % (vm.getPos()[0],vm.getPos()[1]),
        print vm.getRel(), vm.getWheelRel(), "%.3f"%vm.mouseMoveTime()
        vm.leftLimit = vm.bottomLimit = -1
        vm.rightLimit = vm.topLimit = 1
        instr.setText("press 'escape' to quit")
        vm.pointer = new_pointer
Reply all
Reply to author
Forward
0 new messages