0
$\begingroup$

Consider an an InputField object of the form

DynamicModule[{x = 0},
 {InputField[Dynamic@x],Dynamic@stuffDependingOnx}
 ]

What I want is a direct way to trigger some action, EventHandler-style, whenever the value of x is changed from inside the InputField.

I know that I can use EventHandler with CurrentValue["EventKey"], but this triggers whenever I write something inside the input box, not when the value of x actually changes.

I could achieve such an effect by using two variables for x, say x and xTmp, setting xTmp=x at the beginning and putting a control inside the Dynamic to check for equality between xTmp and x, triggering the event whenever they are different, and then setting them to be equal again. However, it seems to me that such a basic functionality should be more directly accessible, though I didn't manage to find it on the documentation.

Is there a direct way to do this?


Some context:

Here is a toy example to illustrate the functionality I'm looking for:

DynamicModule[{n = 2},
 DynamicModule[{points = Thread@{Range[0.1, .9, 1/n], 0}},
  Column@{
    InputField[Dynamic@n],
    LocatorPane[
     Dynamic@points,
     Graphics[{FaceForm[], EdgeForm[Black], 
       Rectangle[{0, -1}, {1, 1}]}]
     ]
    }
  ]
 ]

What I want is to be able to change the InputField, and when confirming the change (pressing enter and exiting the focus of InputField) the number of points should change, and the new points be reset at their starting positions.

Again, I can achieve this with the trick explained above:

DynamicModule[{n = 2, nNew = 2},
 DynamicModule[{points = Thread@{Range[0.1, .9, 1/n], 0}},
  Column@{
    InputField[Dynamic@nNew],
    Dynamic[
     If[nNew != n,
      n = nNew;
      points = Thread@{Range[0.1, .9, 1/n], 0}
      ];
     LocatorPane[
      Dynamic@points,
      Graphics[{FaceForm[], EdgeForm[Black], 
        Rectangle[{0, -1}, {1, 1}]}]
      ]
     ]
    }
  ]
 ]

which does exactly what I want. But isn't there a more direct way to achieve this?

$\endgroup$
  • $\begingroup$ There is no killer solution for that. Can you provide a context? Maybe it is not needed, e.g. Dynamic in other places should be smart enough etc. p.s. keep in mind that unless you use ContinuousAction->True, x is not really changed unless you "finish editing", whatever that means. $\endgroup$ – Kuba Jul 11 '16 at 11:46
  • $\begingroup$ @Kuba see edit . $\endgroup$ – glS Jul 11 '16 at 12:04
  • 1
    $\begingroup$ @glS InputField@Dynamic[n, {Automatic, (points = Thread@{Range[0.1, .9, 1/n], 0}) &}]? $\endgroup$ – Kuba Jul 11 '16 at 12:09
2
$\begingroup$

I think second argument to Dynamic of InputField should help you. With it n is updated to the changed input and at the same time points are reinitialized. Help on input field says you can't use ContinuousAction with general expression, this is why Number type is specified.

DynamicModule[{n = 2},
 DynamicModule[{make, points},
  make[n_Integer] := RandomReal[{-1, 1}, {n, 2}];
  points = make[n];
  Column@{
    InputField[
     Dynamic[n, (n = #; points = make[n]) &],
     Number,
     ContinuousAction -> True,
     ImageSize -> 200],
    LocatorPane[Dynamic@points,
     Graphics[{
       FaceForm[], EdgeForm[Black],
       Rectangle[{-1, -1}, {1, 1}]},
      ImageSize -> 200]
     ]
    }
  ]
 ]

enter image description here

$\endgroup$
  • $\begingroup$ Thanks. This, together with Kuba's suggestion to only trigger the action when the variable change is complete, answers my question $\endgroup$ – glS Jul 11 '16 at 14:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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