Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

We can restrict the movement of locators in a LocatorPane as follows:

locator movement

In the following example, the first locator's movement is confined to the x-axis and the second locator's movement is confined to the y-axis.

Manipulate[LocatorPane[Dynamic[pts], 
 Graphics[{}, PlotRange -> max, Axes -> True, ImageSize -> 350],
 {{{-max, 0}, {max, 0}},
 {{0, -max}, {0, max}}}],
{{pts, {{9, 0}, {0, 11}}}, ControlType -> None}, Initialization :> {max = 25}]

enter image description here

However, a locator can be dragged without necessarily being selected. You can begin dragging a locator by clicking down on just about any point in the four quadrants and dragging from there.

I would like to have the locator respond only to drags that are initiated by "mousedown"ing on the locator itself.

Any ideas as to how I might achieve this?


Addendum In my the more complicated example I've been working with, I've made use of jump parameters to confine locators to integer values:

{{{-maxX, 0}, {maxX, 0}, {1, 0}},
{{0, -maxY}, {0, maxY}, {0, 1}}}

I'm not sure whether such constraints (to integers) can be imposed on locators outside of LocatorPanes.

share|improve this question
add comment

2 Answers

up vote 8 down vote accepted

That is the default (and expected) behaviour of LocatorPane. This is useful in implementing things like colour pickers, for example, where it is convenient to simply click on any point to select that colour and have the locator move there automatically to indicate selection.

To create locators that move only when explicitly clicked and dragged, use a Locator. Here's an example for the scenario in the question:

DynamicModule[{pt1 = {-5, 0}, pt2 = {0, 5}},
    With[{max = 25},
        Graphics[{
            Locator[Dynamic[pt1, (pt1 = {First@#, 0}) &]], 
            Locator[Dynamic[pt2, (pt2 = {0, Last@#}) &]]
            }, PlotRange -> max, Axes -> True, ImageSize -> 350
        ]
    ]
]
share|improve this answer
    
They behave very nicely! –  David Carraher Jul 30 '12 at 21:31
    
The LocatorPane doc says: "LocatorPane[pts,back,range] by default directs any click to the nearest locator." It makes you wonder if there is a non-default setting. I couldn't find anything about that. I also note that this behaviour is the same in a Locator in a Manipulate. It is actually strange that a Locator in a Graphics has a different behaviour. –  Sjoerd C. de Vries Jul 30 '12 at 21:46
    
There is one minor drawback with R.M.'s otherwise excellent solution: if you click away from the Locator, a graphics boarder will appear and remain visible. This does not occur with LocatorPane. –  David Carraher Jul 30 '12 at 21:49
    
@SjoerdC.deVries The next sentence says what the non-default option is — it creates new locators where you clicked, instead of moving the nearest one. So "default" in that context refers to some other behaviour –  rm -rf Jul 30 '12 at 21:56
1  
@DavidCarraher issue with frame can be fixed with Style[Graphics[...], Selectable -> False] –  Vitaliy Kaurov Jul 30 '12 at 22:10
show 10 more comments

This is the bare bone implementation with direct control of mouse events:

DynamicModule[{p = {0, 0}}, EventHandler[Framed@Dynamic[Style[
  Graphics[{Red, Disk[p, 0.2]}, PlotRange -> 2], Selectable -> False]], 
      {"MouseDragged" :> (p = MousePosition["Graphics"])}]]

And this is more or less what you need:

DynamicModule[{p1 = {0, 2}, p2 = {2, 0}}, EventHandler[
  Dynamic[Style[Graphics[{{Red, Disk[{0, Round@p1[[2]]}, .2]}, {Blue, 
       Disk[{Round@p2[[1]], 0}, .2]}}, PlotRange -> 5, Axes -> True], 
    Selectable -> False]],{"MouseDragged" :> (If[
       EuclideanDistance[p1, MousePosition["Graphics"]] < 
        EuclideanDistance[p2, MousePosition["Graphics"]], 
       p1 = MousePosition["Graphics"], p2 = MousePosition["Graphics"]];)}]]

enter image description here

It is a bit hacky, but because of integer settings it works.

share|improve this answer
    
This code selects which locator is closer to the mouse position. It's a nice approach, but unfortunately it doesn't solve my problem. In a more complex implementation that I am designing, there are other graphics objects on the screen (points that look somewhat like the locators). The locators affect, for instance the slope of a line going through the origin. I want to leave it unambiguous about which object,i.e. a particular locator (and not a nearby point) is "responding" to the actions of the mouse. –  David Carraher Aug 1 '12 at 13:39
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.