12
$\begingroup$

Suppose I have a DynamicModule with all sorts of controls to set some parameters for a graphics object.

DynamicModule[{a = 0, b = 0},
  Column[{
    Slider[Dynamic[a]],
    Slider[Dynamic[b]],
    Dynamic[Plot[Sin[(a + 1) t + \[Pi] b], {t, 0, 2 \[Pi]}]]
  }]
]

This graph is updated every time one of the dynamic parameters change. Now pretend my graphics is a really slow 3D plot. How can I construct it so that it only renders the graphic when I tell it to? A button? A mouse event?

$\endgroup$

3 Answers 3

15
$\begingroup$

If you want the user to have absolute control over updates...say, by having an explicit Update button, then you can do so by adding an independent variable to control the updating and changing your Dynamic so that it only tracks that variable. Here, I introduce a variable update, which is an integer. Its value and type don't matter...what matter is that the Dynamic only updates when that variable does:

DynamicModule[{a = 0, b = 0, update = 0}, 
 Column[{Slider[Dynamic[a]], Slider[Dynamic[b]], 
   Button["Update", update++], 
   Dynamic[update; Plot[Sin[(a + 1) t + \[Pi] b], {t, 0, 2 \[Pi]}], 
    TrackedSymbols :> {update}]}]]
$\endgroup$
4
$\begingroup$

I think the following solves your problem. The option that you look for is ContinuousAction -> False. If you use Manipulate then using the same option you will get your requested update button. In the following once you decide where you want to locate your slider then only the computation will be initiated not continuously during the instantaneous slider movement

DynamicModule[{a = 0, b = 0}, 
Column[{Slider[Dynamic[a], {-3, 3, .01}, ContinuousAction -> False], 
Slider[Dynamic[b], {-3, 3, .01}, ContinuousAction -> False], 
Dynamic[Plot3D[Sin[a x + y^2 b], {x, -3, 3}, {y, -2, 2}, 
PlotPoints -> 140, Mesh -> None, MaxRecursion -> 3, 
ImageSize -> 400]], 
Dynamic["Time Count: " <> ToString@Clock[4]]}, 
Frame -> All]]

enter image description here

I used some options for Plot3D to generate a bit heavy graphics and also gave a reference clock cycle of four seconds to sense the computation time after the control triggers are decided.

$\endgroup$
3
$\begingroup$

Using ContinuousAction -> False is a good suggestion, and the simplest solution. If you'd prefer to get some real time feedback even during dragging the slider, you can use ControlActive to temporarily change the value of parameters that affect performance.

DynamicModule[{a = 0, b = 0},
 Column[
  {Slider[Dynamic[a]], Slider[Dynamic[b]],
   Dynamic[
    Plot3D[Sin[a x + b/y], {x, -3, 3}, {y, -2, 2},
     PlotPoints -> ControlActive[20, 100],
     MaxRecursion -> ControlActive[0, 3],
     Mesh -> None,
     ImageSize -> 400]]
   }]]

This is in fact automatically going to happen with the PerformanceGoal setting of functions. The default value of $PerformanceGoal, the value of which depends on relevant controls being active. You can test this using

DynamicModule[{a = 1}, 
 Column[{Slider[Dynamic[a]], Dynamic[{a, $PerformanceGoal}]}]]
$\endgroup$

Your Answer

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

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