8
$\begingroup$

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?

$\endgroup$

4 Answers 4

12
$\begingroup$

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}}]
$\endgroup$
1
  • $\begingroup$ +1 for reminding me to use the $f_{start}$ and $f_{end}$ arguments of Dynamic more often. $\endgroup$ Commented Jun 20, 2012 at 8:11
12
$\begingroup$

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

$\endgroup$
1
  • 1
    $\begingroup$ @Rojo Somehow I knew I'll get at least one upvote b/c of that :) $\endgroup$ Commented Jun 16, 2012 at 23:00
11
$\begingroup$

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.

$\endgroup$
0
$\begingroup$

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"]]]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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