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.

This bit of code sets up a list with the first entry already in it -- {{1,1}}:

Clear[x, y]
x = 1
y = 1
datalist = List[List[x, y]]

Here is a slider by which I can alter x and y by depressing the mouse:

Slider2D[{x, y}, {{0, 0}, {5, 8}, {1, 2}}]

But when I release the mouse button nothing happens of course, except that {x,y} are at some new value inside the slider.

Suppose I have moved the slider to location {3,6}. When I release the mouse button, I want {3,6} to be appended to datalist so it now becomes {{1,1},{3,6}}.

When I am done adding data points I want to save datalist.

How do I create this functionality with making as few changes/additions to the above code as possible?

share|improve this question

4 Answers 4

Another way is to make use of the second argument of Dynamic. When given as a list of two functions, the first element of the second argument will be evaluated when the mouse is dragged, and the second one at the moment that the mouse is released, so in this case the the final value of the slider will be added to dataList.

pt = {1, 1};
dataList = {pt};
Slider2D[Dynamic[pt, {(pt = #) &, AppendTo[dataList, pt] &}], 
    {{0, 0}, {5, 8}, {1, 2}}]
share|improve this answer
    
+1 for reminding me to use the $f_{start}$ and $f_{end}$ arguments of Dynamic more often. –  István Zachar Jun 20 '12 at 8:11

Alternatively, you may use LocatorAutoCreate, which adds the oportunity of adding, moving and removing points "a piaccere":

DynamicModule[{pts = {{-1, 1}/2, {1, 1}/2}}, 
 Column[{LocatorPane[Dynamic[pts], Framed@Graphics[{}], LocatorAutoCreate -> All],
   Dynamic@pts}]]

enter image description here

Usage sample:

i = Import@ "http://worldmapsonline.com/images/OutlineMaps/Flags/Argentina2.jpg" 
DynamicModule[{pts = {{-1, 1}/2, {1, 1}/2}},
              LocatorPane[Dynamic[pts],
                   Show[{i, Graphics@Polygon@Dynamic@pts}, ImageSize -> {300, 300}],
              LocatorAutoCreate -> All]]

enter image description here

share|improve this answer
3  
+1 for the usage sample –  Rojo Jun 16 '12 at 22:58
1  
@Rojo Somehow I knew I'll get at least one upvote b/c of that :) –  belisarius Jun 16 '12 at 23:00

This is a job for EventHandler:

EventHandler[
   Slider2D[Dynamic[{x, y}], {{0, 0}, {5, 8}, {1, 2}}],
   {"MouseUp" :> AppendTo[datalist, {x, y}]},
   PassEventsDown -> True
]

Mathematica graphics

Follow the data acquisition with a Dynamic:

Dynamic[datalist]

{{1,1},{3,4},{2,2},{2,4}}

PassEventsDown -> True is necessary to prevent EventHandler from eating up the MouseDrag events that are necessary to make the Slider2D move. To let Slider2D update x and y the Dynamic is necessary. This is well documented in the Slider2D documentation.

share|improve this answer

The following code is usable and does the trick, except it does not permit constraining entry points to specific values, for example even numbers on the horizontal axis (like years for example). Still, it does everything else, and also permits very flexible adjustment of the size and shape of the input space, so I think it is worth sharing. Instructions follow, and the code begins at the row of ================ signs

Instructions:
You can: add to and adjust data in pts which initially contains one point located at {0,0}. Then save the result by clicking the Button called "Press to Save Edited Data"

Detailed directions: 1--Drag the initial point, located at {0,0} , to where your first point should be. 2--To move a data point, drag it with left mouse button. 3--To add a datapoint you must use alt-click. 4--To remove a datapoint cover it and press alt-click. 5--Once the points are as you like them, press the Save Edited Data Button.

======================================= Remove[pts, newpts, numbrHgrdLns, vmax, vmin, disTweenHgrdLns, locsHgrdLns, numbrVgrdLns, hmax, hmin, disTweenVgrdLns, locsVgrdLns, i, j, imgSze, data, asPr]

Manipulate[Column[{ {"Number of horizontal gridlines: ", numbrHgrdLns = IntegerPart[(vmax - vmin)/disTweenHgrdLns]}; locsHgrdLns = vmin + Table[i disTweenHgrdLns, {i, 1, numbrHgrdLns}];

{"Number of vertical gridlines: ", numbrVgrdLns = IntegerPart[(hmax - hmin)/disTweenVgrdLns]};

locsVgrdLns = hmin + Table[j disTweenVgrdLns, {j, 1, numbrVgrdLns}];

ListPlot[{{{hmin, vmin}, {hmax, vmax}}, pts}, PlotRange -> {{hmin, hmax}, {vmin, vmax}}, PlotStyle -> Directive[Red, PointSize[.03]], GridLines -> {locsVgrdLns, locsHgrdLns}, GridLinesStyle -> {{Red, Thick}, {Orange, Thick}}, ImageSize -> imgSze, AspectRatio -> 2/asPr], Dynamic[newpts = pts]}],

{{vmax, 11, "Vertical max. of graph space: "}, FieldSize -> Tiny}, {{vmin, 0, "Vertical min. of graph space (Neg. value ok): "}, FieldSize -> Tiny}, {{disTweenHgrdLns, 1.000, "Distance between horizontal gridlines: "}, FieldSize -> Tiny}, {{hmax, 23, "Horizontal max. of graph space: "}, FieldSize -> Tiny}, {{hmin, 0, "Horiz. min. of graph space: "}, FieldSize -> Tiny}, {{disTweenVgrdLns, 2.000, "Distance between vertical gridlines: "}, FieldSize -> Tiny}, {{imgSze, 200, "Enlarge size of graph via slider: "}, 200, 2000},

{{asPr, 2, "Graph aspect ratio --make graph flatter/taller: "}, .5, 10},

{{pts, {{0, 0}}}, Locator, LocatorAutoCreate -> True}, ControlPlacement -> Top] pts Button["Press to Save Edited Data", Put[newpts, StringJoin[NotebookDirectory[], "savedDta.m"]]]

share|improve this answer

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.