Re: Locators disappearing in LocatorPane (although working)
- To: mathgroup at smc.vnet.net
- Subject: [mg124550] Re: Locators disappearing in LocatorPane (although working)
- From: John Fultz <jfultz at wolfram.com>
- Date: Tue, 24 Jan 2012 05:08:27 -0500 (EST)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- Reply-to: jfultz at wolfram.com
I wasn't able to immediately reproduce this, but I suspect I know what's causing it anyway. The Dynamic around the LocatorPane is causing the LocatorPane to be reconstructed underneath you while you're dragging. Generally, you should construct controls so that they're not inside Dynamics that will trigger while you're interacting with those controls, since this can create instability and may even be completely impossible for a human, yet alone an algorithm, to figure out how you intend to deal with selections, drags, etc. Normally, the Dynamic wouldn't retrigger and would just be so much code fluff if you had properly scoped all of the contents in Dynamic. But in this case, you have (elided for emphasis): Dynamic[LocatorPane[..., ...[BezierCurve[Dynamic[P], SplineDegree->Length[P]]]] Nowhere is Length[P] wrapped in a Dynamic below the scope of the top-level Dynamic, so every time P changes, the entire LocatorPane reconstructs, and you risk losing track of which Locator you're currently dragging. It's tempting to just populate Dynamics everywhere until things appear to work, but it really helps to stop and think about how Dynamic works. Doing so will help you to make sure that you not only avoid this kind of situation, but improve efficiency of the resulting interface as well. For this example, I recommend wrapping a Dynamic around BezierCurve and removing all other Dynamics associated with the LocatorPane. Additionally, you have a huge unnecessary inefficiency. The Dynamic wrapping the 3D graphic also encompasses a second global variable. When this global variable changes, it triggers to cause the Dynamic to trigger again. So this Dynamic is triggering twice as often as it needs to. There are various ways to work around this...the one I'll show below uses the TrackedSymbols option to only track the variables you want. DynamicModule[{P = 1/2 {{1, 1}, {-1, 1}, {1, -1}}, \[ScriptCapitalP]}, GraphicsRow[{LocatorPane[Dynamic[P], Framed@Graphics[ Dynamic[BezierCurve[P, SplineDegree -> Length[P]]], Axes -> True, PlotRange -> {{-1, 1}, {-1, 1}}], LocatorAutoCreate -> True], Dynamic[\[ScriptCapitalP] = Append[#, 0] & /@ P; Graphics3D[{Sphere[\[ScriptCapitalP], 0.05], {Gray, Opacity[0.5], Tube[Line[\[ScriptCapitalP]], 0.015]}, Tube[BezierCurve[\[ScriptCapitalP], SplineDegree -> Length[\[ScriptCapitalP]]], .03]}, Axes -> True, PlotRange -> 1], TrackedSymbols :> {P}]}]] Sincerely, John Fultz jfultz at wolfram.com User Interface Group Wolfram Research, Inc. On Sat, 21 Jan 2012 05:13:29 -0500 (EST), Chris Young wrote: > The Locators are vanishing from sight before they reach the edge of the > Locator pane, although they are still working. > > DynamicModule[ > {P = 1/2 {{1, 1}, {-1, 1}, {1, -1}}, > \[ScriptCapitalP]}, > > GraphicsRow [ > { > Dynamic[ > LocatorPane[ > Dynamic[P], > Framed @ Graphics[ > BezierCurve[Dynamic[P], SplineDegree -> Length[P]], > Axes -> True, > PlotRange -> {{-1, 1}, {-1, 1}} > ], > LocatorAutoCreate -> True > ] > ], > > Dynamic[ > \[ScriptCapitalP] = Append[#, 0] & /@ P; > Graphics3D[ > { > Sphere[\[ScriptCapitalP], 0.05], > {Gray, Opacity[0.5], Tube[Line[\[ScriptCapitalP]], 0.015]}, > Tube[ > BezierCurve[\[ScriptCapitalP], > SplineDegree -> Length[\[ScriptCapitalP]]], .03] > }, > Axes -> True, > PlotRange -> 1 > ] > ] > } > ] > ]