5
$\begingroup$

I have a plot with interactive controls. I'd like to give the user the option between having the plot automatically update (when the plot's parameters are changed with the slider) and having the update happen only when an 'update' button is pushed. I've been spinning my wheels on this for a long time. Any and all help is appreciated.

$\endgroup$
4
  • 2
    $\begingroup$ Please provide a simple example. $\endgroup$
    – bbgodfrey
    Commented Jul 20, 2016 at 20:54
  • 1
    $\begingroup$ By the way you might want to look at ContinuousAction if you have not done so already. It is not an answer to your question but it can provide a reasonable in-between in some cases. $\endgroup$
    – Mr.Wizard
    Commented Jul 20, 2016 at 21:25
  • 1
    $\begingroup$ And if performance is an issue then ControlActive is good to know. $\endgroup$
    – Kuba
    Commented Jul 20, 2016 at 21:26
  • 1
    $\begingroup$ @Kuba Good point! nibudd, please see (8072) for one example, or search the site for others $\endgroup$
    – Mr.Wizard
    Commented Jul 20, 2016 at 21:27

1 Answer 1

10
$\begingroup$

Edit

Can you think of another way to accomplish the same thing [...]? It would be nice to have a solution that didn't involve duplicating each slider.

-nibudd

DynamicModule[{a = 1, tempA = 1, auto = True}
 ,
 ifAuto = Dynamic[
     If[auto, Identity, Setting]@#, 
     TrackedSymbols :> {auto}
 ] &;
 
 Column[{
   ifAuto @ Dynamic @ Plot[Sin[a x], {x, 0, 1}],
   Slider[Dynamic[a], {1, 10}],
   Checkbox[Dynamic[auto]],
   Button["Update", auto = True; FinishDynamic[]; auto = False;, 
    Method -> "Queued", Enabled -> Dynamic@Not@auto]
   }]
 ]
  • ifAuto function is meant to be used on Dynamic parts of GUI that you want to be affected by this behaviour.

  • ifAuto's Dynamic output is triggered only when variable auto changes

  • If auto === True then it acts as it wasn't there. E.g Dynamic[Plot[...]...] is shown and the FrontEnd will take care about its updates according to what was set there.

    If[ from ifauto is only run when auto changes so it does not affect the performance, neat. Read more in tutorial/AdvancedDynamicFunctionality/Nesting Dynamic

  • If auto === False then Setting @ Dynamic @ Plot[... is shown, effectively stripping Dynamics and leaving Plot[... which won't be updated by a's changes (because of the very outer TrackedSymbols:>{auto}.


Initial approach

The idea is to switch controllers between main a variable and a temporary one tempA's.

The Checkbox toggles that. It also makes both variables synchronized so that the transistion is "smooth".

DynamicModule[{a = 1, tempA = 1, auto = True},
 Column[{
   Dynamic @ Plot[Sin[a x], {x, 0, 1}],
   PaneSelector[
    {
     True -> Slider[Dynamic[a], {1, 10}],
     False -> Slider[Dynamic[tempA], {1, 10}]
     },
    Dynamic@auto
    ],
   Checkbox[Dynamic[auto, If[auto = #, a = tempA, tempA = a] &]],
   Button["Update", a = tempA, Enabled -> Dynamic@Not@auto]
   }
  ]
 ]

enter image description here

Instead of PaneSelector you can use

`Slider[Dynamic[tempA, (tempA = #; If[auto, a = tempA]) &], {1, 10}]`

but spamming If whenever you move a Slider is not neat.

$\endgroup$
7
  • $\begingroup$ This is exactly the kind of thing I was trying to achieve. Now to understand what you've done here - thank you! $\endgroup$
    – nibudd
    Commented Jul 20, 2016 at 21:52
  • $\begingroup$ If you'll indulge me, I have some questions about how this works: 1. What is the If pure function taking as its argument, the value of Checkbox? 2. What is the meaning of auto = # in the first argument of If? Is # being evaluated to determine which expression to execute (a = tempA or tempA = a) and then assigning that value to auto? 2b. If so, why is that necessary? Isn't auto already tied to the Checkbox? 3. What is the meaning of @ here? I can't find any documentation on this kind of usage (Dynamic @ Plot[..., Dynamic @ auto, or Dynamic @ Not @ auto) $\endgroup$
    – nibudd
    Commented Jul 21, 2016 at 15:45
  • 1
    $\begingroup$ @nibudd 1. take a look at docs for Dynamic, the second argument of Dynamic can be a function which does whatever you want with the state of the controller. # is a slot which will be filled with that state, so True or False. 2. auto = # has 2 roles, assigns Checkbox state to auto and returns this value so we can synchronize a with tempA (when a or tempA is active the other isn't though we don't want it's old value to pop up after switching). Hope that was clear. About @, take a look at What the @#%^&*?! $\endgroup$
    – Kuba
    Commented Jul 21, 2016 at 16:22
  • $\begingroup$ I did read the documentation on Dynamic, but since I'm relatively new to Mathematica, I did not find it terribly helpful. I appreciate you clearing up my confusion. Can you think of another way to accomplish the same thing by using the TrackedSymbols attribute of Plot? I've been trying to do this with something like TrackedSymbols :> Dynamic[list, If[manualUpdate = #, list = {update}, list = {a, b}] &]' where update` is tied to my update button, and a, b are tied to two different sliders. It would be nice to have a solution that didn't involve duplicating each slider. $\endgroup$
    – nibudd
    Commented Jul 21, 2016 at 16:52
  • 1
    $\begingroup$ @nibudd I see, take a look at the edit, that should be it. $\endgroup$
    – Kuba
    Commented Jul 21, 2016 at 17:47

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.