1
$\begingroup$

I am building a Dynamic application and I'm having some trouble understanding exactly how Refresh should be implemented.

The main point of work for this is a LocatorPane, whose background has two parts: (a) one which depends on the value of its Locator, and (b) one which depends on external variables, combined using Show. The dependence on the Locator is easy and quick to implement, but the dependence on the external variables is slower. I would like to separate these two tracks so that part (b) is only evaluated when it is needed. That is, I want updates of the Locator position to only trigger updating of part (a).

A simple working example is the following:

DynamicModule[
 {a = 0.5, point = {1, 1}},
 Column[{
   Slider[Dynamic[a]],
   LocatorPane[
    Dynamic[point],
    Dynamic[
     Show[
      ContourPlot[
       Sin[a x y], {x, -5, 5}, {y, -5, 5}
       , ImageSize -> 300, PlotRangePadding -> None
       ],
      Graphics[Line[{{0, 0}, point}]]
      ]
     ]
    ],
   Dynamic[point]
   }]
 ]

Here changing the value of a via the slider causes the ContourPlot to update, which makes it go fuzzy (at a lower number of PlotPoints) while it is recalculated. This is expected behaviour. However, clicking on the LocatorPane also causes this behaviour, which is unnecessary as it's only the Line that needs to be updated.

Thus:

enter image description here

Now this is the expected behaviour from the code as written, and Mathematica needs to be told explicitly to hold off evaluation, on which bits of the plot, and in which conditions.

From what I understand of the Refresh documentation, it should suffice to contain the ContourPlot inside a Refresh call, setting the TrackedSymbols to a. However, the resulting code,

DynamicModule[
 {a = 0.5, point = {1, 1}},
 Column[{
   Slider[Dynamic[a]],
   LocatorPane[
    Dynamic[point],
    Dynamic[
     Show[
      Refresh[
       ContourPlot[
        Sin[a x y], {x, -5, 5}, {y, -5, 5}
        , ImageSize -> 300, PlotRangePadding -> None
        ]
       , TrackedSymbols -> {a}
       ],
      Graphics[Line[{{0, 0}, point}]]
      ]
     ]
    ],
   Dynamic[point]
   }]
 ]

has the same behaviour as above. Moreover, trying to encase the Refresh in a nested Dynamic call simply causes Show to give an error message (Could not combine the graphics objects). On the other extreme, putting the whole Show inside the Refresh scope causes the Line to freeze and stop following the pointer around until the slider is manipulated.

How can I successfully decouple the dynamic updating of these two parts of the background, so that each part will only update when it needs to?

$\endgroup$
  • 1
    $\begingroup$ Refresh tells what to do to the Dynamic it is in, and the whole Dynamic will be updated, it can not focus only on Refresh. This is tricky function :) a little related: 78580 $\endgroup$ – Kuba May 26 '15 at 7:28
2
$\begingroup$

Not sure about how to use Refresh in this case, but without it enclosing Show and point in Dynamic works:

DynamicModule[{a = 0.5, point = {1, 1}},
 Column@{
   Slider@Dynamic@a,
   LocatorPane[
    Dynamic@point,
    Dynamic@Show[
      ContourPlot[Sin[a x y], {x, -5, 5}, {y, -5, 5}, 
       ImageSize -> 300, PlotRangePadding -> None],
      Graphics@Line@{{0, 0}, Dynamic@point}
      ]
    ], Dynamic@point
   }
 ]

This way only the inner Dynamic@point is triggered when changing the value of point.

$\endgroup$

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.