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.

I have this code:

DynamicModule[{r = 1},
Grid[{{Slider[Dynamic[r]], SpanFromLeft},
{f[Dynamic[r]], g[Dynamic[r]]}}]]

While I move the slider, $f$ ang $g$ are evaluated continually, but only $f$ should be. I want $g$ to be evaluated only with the final value of $r$. (When I release left click)

How to do this?

share|improve this question
add comment

3 Answers 3

up vote 9 down vote accepted

ControlActive is useful for this purpose:

DynamicModule[{r = 1, old = 1}
, Grid[
    { {Slider[Dynamic[r]], SpanFromLeft}
    , {Dynamic[f[r]], Dynamic[g[ControlActive[r, old = r]; old]]}
    }
  ]
]

The variable old has been introduced to hold the "old" value of r. The key expression is ControlActive[r, old = r]; old, which always returns the value of old. However, it also checks to see if there is a control actively updating r. If not, old is assigned the final value of r.

DynamicWrapper

The expressiong[ControlActive[...];old] is a bit obscure. It mixes two concerns: the display of g[old], and the synchronization logic between the slider and the variable old. It would be nice if we could separate these concerns, especially if old were referenced for display in multiple places.

Version 8 introduced DynamicWrapper for this purpose. It allows us to separate out the synchronization logic:

DynamicModule[{r = 1, old = 1}
, DynamicWrapper[
    Grid[
      { {Slider[Dynamic[r]], SpanFromLeft}
      , {Dynamic[f[r]], Dynamic[g[old]], Dynamic[h[old]]}
      }
    ]
  , ControlActive[r, old = r]
  ]
]

The display expressions Dynamic[g[old]] and Dynamic[h[old]] are now nice and clean. The sychronization logic has been moved to the second argument of DynamicWrapper. That logic will be active as long as the wrapped element, Grid[...], is visible.

share|improve this answer
add comment

Dynamic has this build into it. You can take advantage of the Dynamic second and third arguments. The second argument of evaluate as the dynamic is being updated. The third argument is evaluated when the mouse is released. Which is what you want.

To illustrate, here is an example, where f[r] and g[r] are inside the arguments of the slider itself. This is where you would actually do the call from. But to see the effect, I put the values of their calls in the last entry of the grid. It shows, with a time stamp, that only the f[r] is called while the mouse is moving, and g[r] is only called when the mouse is released.

enter image description here

DynamicModule[{r = 1, fv = 0, gv = 0},

 g[z_] := Column[{"g called ", z, Date[]}];
 f[z_] := Column[{"f called ", z, Date[]}];

 Grid[{
   {

    Slider[Dynamic[r,
      {(r = #) &, 
       (r = #; fv = f[r]) &,  (*called as the slider moves*)
       (r = #; gv = g[r]) &   (*called only when the mouse is released*)
       }]
     ], SpanFromLeft},

   {Dynamic@fv, Dynamic@gv} (*to see the effect only. Needed for display*)

   }, Frame -> All
  ]
 ]
share|improve this answer
add comment

Not much to add to the code below. Indeed, it seems EventHandler is a solution to your problem. You need PassEventsDown to let the slider update.

DynamicModule[{r = 1, s = 1},
 EventHandler[
  Grid[
   {
    {Slider[Dynamic[r]], SpanFromLeft},
    {Dynamic[f[r]], Dynamic[g[s]]}
    }
   ],
  {"MouseUp" :> (s = r)}, PassEventsDown -> True
  ]
 ]
share|improve this answer
add comment

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.