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:
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?
Refresh
tells what to do to theDynamic
it is in, and the wholeDynamic
will be updated, it can not focus only onRefresh
. This is tricky function :) a little related: 78580 $\endgroup$