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.

In trying to implement Vitaly's suggestion about how to take control of Locator events, I have been able to make headway using DynamicModule. However, the ultimate destination is a demonstration, so I'd like to make the code work in Manipulate.

The Code

The following pared-down version works fine. It places 5 locators in a coordinate space with x and y axes displayed.

DynamicModule[{p1 = {0, 2}, p2 = {2, 0}, p3 = {4, -3}, p4 = {-3, 3}, p5 = {1, 1}},
EventHandler[
dQ[p_, q_] := EuclideanDistance[p, MousePosition["Graphics"]] < 
EuclideanDistance[q, MousePosition["Graphics"]];
Dynamic[
 Style[Graphics[{
  {Red, Disk[{0, Round@p1[[2]]}, .2]},
  {Blue, Disk[Round@p2, .2]},
  {Green, Disk[p3, .2]},
  {Brown, Disk[p4, .2]},
  GraphicsGroup[{Black, Line[{.1 {0, 1.5} + p5, .1 {0, 3} + p5}], 
    Line[{.1 {0, -1.5} + p5, .1 {0, -3} + p5}], 
    Line[{.1 {-1.5, 0} + p5, .1 {-3, 0} + p5}], 
    Line[{.1 {1.5, 0} + p5, .1 {3, 0} + p5}], 
    Circle[{0, 0} + p5, .2], Gray, Disk[p5, .1]}]},
 PlotRange -> 5, Axes -> True],Selectable -> False]],
 {"MouseDragged" :>
  (Which[
  dQ[p1, p2] && dQ[p1, p3] && dQ[p1, p4] && dQ[p1, p5], 
  p1 = MousePosition["Graphics"],
  dQ[p2, p1] && dQ[p2, p3] && dQ[p2, p4] && dQ[p2, p5], 
  p2 = MousePosition["Graphics"],
  dQ[p3, p1] && dQ[p3, p2] && dQ[p3, p4] && dQ[p3, p5], 
  p3 = MousePosition["Graphics"],
  dQ[p4, p1] && dQ[p4, p2] && dQ[p4, p3] && dQ[p4, p5], 
  p4 = MousePosition["Graphics"],
  dQ[p5, p1] && dQ[p5, p2] && dQ[p5, p3] && dQ[p5, p4], 
  p5 = MousePosition["Graphics"]])}]]

Moving to Manipulate

The issue is really quite simple. How can I successfully wrap this code in Manipulate? I've tried this:

 Manipulate[ 
   <above code>,
   {x,1,12,Slider} ]

[The slider serves no purpose at the moment.]

What happens

The manipulate screen appears as expected. However, evaluation goes into a loop. The cell right bracket blinks endlessly.

What causes this loop? Why doesn't it occur when I use DynamicModule without Manipulate?

share|improve this question
add comment

2 Answers

up vote 6 down vote accepted

You shouldn't have initialization code inside of the Manipulate. You're defining the function dQ inside the Manipulate, and by moving that definition to the Initialization option of Manipulate, you can make this behave much better.

Manipulate[
 DynamicModule[{p1 = {0, 2}, p2 = {2, 0}, p3 = {4, -3}, p4 = {-3, 3}, 
   p5 = {1, 1}}, EventHandler[
   Dynamic[
    Style[Graphics[{{Red, Disk[{0, Round@p1[[2]]}, .2]}, {Blue, 
        Disk[Round@p2, .2]}, {Green, Disk[p3, .2]}, {Brown, 
        Disk[p4, .2]}, 
       GraphicsGroup[{Black, Line[{.1 {0, 1.5} + p5, .1 {0, 3} + p5}],
          Line[{.1 {0, -1.5} + p5, .1 {0, -3} + p5}], 
         Line[{.1 {-1.5, 0} + p5, .1 {-3, 0} + p5}], 
         Line[{.1 {1.5, 0} + p5, .1 {3, 0} + p5}], 
         Circle[{0, 0} + p5, .2], Gray, Disk[p5, .1]}]}, 
      PlotRange -> 5, Axes -> True], 
     Selectable -> 
      False]], {"MouseDragged" :> (Which[
       dQ[p1, p2] && dQ[p1, p3] && dQ[p1, p4] && dQ[p1, p5], 
       p1 = MousePosition["Graphics"], 
       dQ[p2, p1] && dQ[p2, p3] && dQ[p2, p4] && dQ[p2, p5], 
       p2 = MousePosition["Graphics"], 
       dQ[p3, p1] && dQ[p3, p2] && dQ[p3, p4] && dQ[p3, p5], 
       p3 = MousePosition["Graphics"], 
       dQ[p4, p1] && dQ[p4, p2] && dQ[p4, p3] && dQ[p4, p5], 
       p4 = MousePosition["Graphics"], 
       dQ[p5, p1] && dQ[p5, p2] && dQ[p5, p3] && dQ[p5, p4], 
       p5 = MousePosition["Graphics"]])}]], {x, 1, 12, Slider}, 
 Initialization :> (dQ[p_, q_] := 
    EuclideanDistance[p, MousePosition["Graphics"]] < 
     EuclideanDistance[q, MousePosition["Graphics"]])]

EDIT:

I should say something else about this answer. I answered the question you asked, but the way I answered it exposes another potential problem. Manipulate wraps its entire contents in a Dynamic. If that outer Dynamic happens to re-trigger, it will recreate the DynamicModule and reinitialize all of your DynamicModule variables. This would certainly happen when you close and reopen the notebook. It could also happen if you add dependencies to the Manipulate variables outside of the inner Dynamic. So, really, a better version of my answer would be to move the DynamicModule out of the Manipulate like this:

DynamicModule[{p1 = {0, 2}, p2 = {2, 0}, p3 = {4, -3}, p4 = {-3, 3}, 
  p5 = {1, 1}}, Manipulate[EventHandler[
   Dynamic[
    Style[Graphics[{{Red, Disk[{0, Round@p1[[2]]}, .2]}, {Blue, 
        Disk[Round@p2, .2]}, {Green, Disk[p3, .2]}, {Brown, 
        Disk[p4, .2]}, 
       GraphicsGroup[{Black, Line[{.1 {0, 1.5} + p5, .1 {0, 3} + p5}],
          Line[{.1 {0, -1.5} + p5, .1 {0, -3} + p5}], 
         Line[{.1 {-1.5, 0} + p5, .1 {-3, 0} + p5}], 
         Line[{.1 {1.5, 0} + p5, .1 {3, 0} + p5}], 
         Circle[{0, 0} + p5, .2], Gray, Disk[p5, .1]}]}, 
      PlotRange -> 5, Axes -> True], 
     Selectable -> 
      False]], {"MouseDragged" :> (Which[
       dQ[p1, p2] && dQ[p1, p3] && dQ[p1, p4] && dQ[p1, p5], 
       p1 = MousePosition["Graphics"], 
       dQ[p2, p1] && dQ[p2, p3] && dQ[p2, p4] && dQ[p2, p5], 
       p2 = MousePosition["Graphics"], 
       dQ[p3, p1] && dQ[p3, p2] && dQ[p3, p4] && dQ[p3, p5], 
       p3 = MousePosition["Graphics"], 
       dQ[p4, p1] && dQ[p4, p2] && dQ[p4, p3] && dQ[p4, p5], 
       p4 = MousePosition["Graphics"], 
       dQ[p5, p1] && dQ[p5, p2] && dQ[p5, p3] && dQ[p5, p4], 
       p5 = MousePosition["Graphics"]])}], {x, 1, 12, Slider}, 
  Initialization :> (dQ[p_, q_] := 
     EuclideanDistance[p, MousePosition["Graphics"]] < 
      EuclideanDistance[q, MousePosition["Graphics"]])]]
share|improve this answer
    
I continue to have an unending updating problem with this code. Perhaps I didn't understand. You eliminated the DynamicModule? –  David Carraher Feb 4 '13 at 0:34
    
@DavidCarraher Sorry, I had a typo/oversight in my original answer which made the resulting code not clear. I've edited and just included the entire code, along with a slight clarifying statement about the nature of the edit. –  John Fultz Feb 4 '13 at 1:06
    
Thanks, nice how the Manipulate is wrapped in a DynamicModule. –  David Carraher Feb 4 '13 at 3:28
add comment

One way to do this is to add TrackedSymbols option to Manipulate - so it will update only when "tracked" variables are changed.

Manipulate[ 
   <above code>,
   {x,1,12,Slider}, TrackedSymbols :> {x} ]

This is the way when you'd like to specify specific controls. Another way to do the same thing for all variables that are listed in controls is

Manipulate[ 
   <above code>,
   {x,1,12,Slider}, TrackedSymbols :> True ]
share|improve this answer
    
So simple a solution to so aggravating a problem. Thanks. –  David Carraher Feb 4 '13 at 0:17
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.