I would like to add a Locator
to a figure displayed by Manipulate
when I click inside the figure, at the location where I click, and to have this trigger an update of the figure. I would also like to have clicking on an existing Locator
remove it, and dragging a locator reposition it (again, redrawing the figure in response in each case).
For (a silly) example, I would like clicking anywhere in the region displayed by
With[{locs = {}},
Manipulate[Graphics[Text[locs, {0, 0}], PlotRange -> 2],
{{q, {1, 1}}, Locator,
Appearance -> Graphics[{Green, Disk[{0, 0}, .1]}, ImageSize -> 10]},
{{p, locs}, Locator,
Appearance -> Graphics[{Red, Disk[{0, 0}, .1]}, ImageSize -> 10]}]]
to add the corresponding Point
to locs
, and for clicking on any p
Locator
to remove it from locs
, with the text, updating accordingly in response to additions, deletions or repositionings of a Locator
.
To make things hard, I have another locator q
that needs to coexist with the one to which I would like to add/remove; and p
and q
have different appearances.
Answer
I would approach the overall goal of the program in a different way that avoids the limitations* of Manipulate
. I would store a list of all the locators in one variable, with the permanent locator(s) at the beginning of the list. The transient locators can be added and removed with ALT+click. The permanent locators are maintained by the option of the form LocatorAutoCreate -> min
, where min
is the number of permanent locators.
Using With
to assign symbols to represent the parts of the list locs
of locators seems slightly inelegant, but overall the approach has the advantage of being simple.
Manipulate[
With[{q = locs[[1]], p = Drop[locs, 1]},
Graphics[Text[locs, {0, 0}], PlotRange -> 2]
],
{{locs, {{1, 1}}}, Locator, LocatorAutoCreate -> 1}
]
*Limitation: When several Locator
controls, p
, q
, ..., appear in a Manipulate
, a LocatorPane
is created of the form
LocatorPane[Dynamic[{p, q, ...}], ...]
The option LocatorAutoCreate
can be passed to the LocatorPane
; however, it does not work because the length of the list {p, q, ...}
cannot be changed.
Update: Appearance
The appearance of the locators may be controlled in two ways. The documented, and hence common, solution is to use invisible locators and insert graphics primitives into the Graphics
:
Manipulate[
With[{q = locs[[1]], p = Drop[locs, 1]},
Graphics[{
Text[locs, {0, 0}],
Locator[q], {Red, PointSize[Large], Point[p]},
PlotRange -> 2]
],
{{locs, {{1, 1}}}, Locator, LocatorAutoCreate -> 1}
]
Another way is to use the option setting
Appearance -> {Automatic, Graphics[{Red, Disk[]}, ImageSize -> 10]}
The last specification is repeated when there are more than two locators, a behavior that I could not find documented.
Comments
Post a Comment