Advanced Dynamic Functionality
"Introduction to Manipulate"
and "Introduction to Dynamic"
provide most of the information you need to use Mathematica
's interactive features accessible through the functions Manipulate
, and DynamicModule
. This tutorial gives further details on the workings of Dynamic
and describes advanced features and techniques for achieving maximum performance for complex interactive examples.
Many examples in this tutorial display a single output value and use Pause
to simulate slow calculations. In real life, you will instead be doing useful computations and displaying sophisticated graphics or large tables of values.
Please note that this is a hands-on tutorial. You are expected to actually evaluate each of the input lines as you reach them in your reading, and watch what happens. The accompanying text will not make sense without evaluating as you read.
Module versus DynamicModule
have similar syntax and in many respects behave similarly, at least at first glance. They are, however, fundamentally different in such areas as when their variables are localized, where the local values are stored, and in what universe the variables are unique.
works by replacing all occurrences of its local variables with new, uniquely named variables, constructed so that they do not conflict with any variables in the current session of the Mathematica
You can see the names of these localized variables by allowing them to "escape" the context of the module without having been assigned a value.
The local variables can be updated dynamically just like any other variables.
Both examples produce seemingly independent sliders that allow separate settings of separate copies of the variable x. The problem with sliders inside Module is that a different kernel session may coincidentally share the same localized variable names. So if this notebook is saved and then reopened sometime later, the sliders may "connect" to variables in some other Module that happen to have the same local variables at that time.
This will not happen with the sliders inside DynamicModule because DynamicModule waits to localize the variables until the object is displayed in the front end and generates local names that are unique to the current session of the front end. Localization happens when DynamicModule is first created as output and then repeats anew each time the file that contains DynamicModule is opened, so there can never be a name conflict among examples generated in different sessions.
Variables generated by Module
are purely kernel session variables; when the kernel session ends, the values are irretrievably lost. DynamicModule
, on the other hand, generates a structure in the output cell that is responsible for maintaining the values of the variables, allowing them to be saved in files. This is a somewhat subtle concept, best explained by way of two analogies. First, you can think of DynamicModule
as a sort of persistent version of Module
The module in this example evaluates a series of expressions in order, and from one line to the next the values of all the local module variables are preserved (obviously). You can have as many lines as you like in the compound expression, but they all have to be there at the start; once the Module
has finished execution, it evaporates along with all its local variables.
, on the other hand, creates an environment in which evaluations of expressions in Dynamic
that appear within the body of the DynamicModule
are like additional lines in the compound expression in the previous example. From one dynamic update to the next the values of all the variables are preserved, just as if the separate evaluations were separate lines in a compound expression, all within the local variable context created by DynamicModule
This preservation of variable values extends not just to subsequent dynamic evaluations within the same session, but to all future sessions. Because all the local variable values are stored and preserved in the notebook file, if the notebook is opened in an entirely new session of Mathematica
, the values will still be there, and dynamic updates will resume just where they left off. DynamicModule
is like an indefinitely extendable Module
Another way to think about the difference between Module
is that while Module
localizes its variables for a certain duration of time
(while the body of the module is being evaluated), DynamicModule
localizes its variables for a certain area of space
in the output.
As long as that space of the output remains in existence, the values of the variables defined for it will be preserved, allowing them to be used in subsequent evaluations of Dynamic
expressions within the scope (area) of the DynamicModule
. Saving the output into a file puts that bit of real estate into hibernation, waiting for the moment when the file is opened again. (In computer science terms, this is sometimes referred to as a freeze-dried or serialized object.)
The ability of DynamicModule
to preserve state across sessions is also a way of extending the notion of editing in a file. Normally when you edit text or expressions in a file, save the file, and reopen it, you expect it to open the way you left it. Editing means changing the contents of a file.
Ordinary kernel variables do not have this property; if you make an assignment to x
, then quit and restart Mathematica
does not have that value anymore. There are several reasons for this, not least of which is the question of where
the value of x
should be saved.
answers this question by defining a specific location (the output cell) where values of specific variables (the local variables) should be preserved. Arbitrary editing operations, like moving a slider, typing in an input field, or dragging a dynamic graphics object, change the values of the local variables. And since these values are automatically preserved when the file is saved, the sliders, and other objects, open exactly where they were left. Thus DynamicModule
lets you make any quantity editable in the same way that text and expressions can be edited and saved in notebook files.
Front End Ownership of DynamicModule Variable Values
Ordinary variables in Mathematica
are owned by the kernel. Their values reside in the kernel, and when you ask Mathematica
to display the value in the front end, a transaction is initiated with the kernel to retrieve the value. The same is true of dynamic output that refers to the values of ordinary variables.
When one slider is moved, the other 499 move in sync with it. This requires 500 separate transactions with the kernel to retrieve the value of x
. (The semantics of Mathematica
are complex enough that there is no guarantee that evaluating x
several times in a row will actually return the same value each time: it would not be possible for the front end to improve efficiency by somehow sharing a single value retrieved from the kernel with all the sliders.)
Variables declared with DynamicModule
, on the other hand, are owned by the front end. Their values reside in the front end, and when the front end needs a value, it can be retrieved locally with very little overhead.
The following example thus runs noticeably faster.
If a complex function is applied to such a variable, its value must of course be sent to the kernel. This happens transparently, with each side of the system being kept informed on a just-in-time basis of any changes to variable values.
Whether it is better to use a normal kernel variable or a DynamicModule
variable in a given situation depends on a number of factors. The most important is the fact that values of all DynamicModule
variables are saved in the file when the notebook is saved. If you need a value preserved between sessions, it must be declared in a DynamicModule
. On the other hand, a temporary variable holding a large table of numbers, for example, might be a poor choice for a DynamicModule
variable as it could greatly increase the size of the file. It is quite reasonable to nest a Module
inside a DynamicModule
and vice versa, or to partition variables between the front end and kernel.
In many situations the limiting factor in performance is the time needed to retrieve information from the kernel: by making variables local to the front end, speed can sometimes be increased dramatically.
Automatic Updates of Dynamic Objects
The specification for dynamic output is simple: Dynamic[expr]
should always display the value you would get if you evaluated expr
now. If a variable value, or some other state of the system, changes, the dynamic output should be updated immediately. Of course, for efficiency, not every dynamic output should be reevaluated every time any variable changes. It is critical that dependencies be tracked so that dynamic outputs are evaluated only when necessary.
Consider these two expressions.
The first expression might change its value any time the value of a
, or c
changes, or if any patterns associated with a
, or c
are changed. The second expression depends on a
(but not c
) while a
and on a
(but not b
) while a
. If a
is neither True
, then it depends only on a
(because the If
statement returns unevaluated).
Figuring out these dependencies a priori is impossible (there are theorems to this effect), so instead the system keeps track of which variables or other trackable entities are actually encountered during the process of evaluating a given expression. Data is then associated with those variable(s) identifying which dynamic expressions need to be notified if the given variable receives a new value.
An important design goal of the system is to allow monitoring of variable values by way of dynamic output referencing them, without imposing any more load than absolutely necessary on the system, especially if the value of the variable is being changed rapidly.
Consider this simple example.
When the dynamic output is created, it is evaluated, and the symbol x
is tagged with information identifying the output that needs to be updated if its value should be changed.
When the loop is started and x
is first given a new value, the data associated with it is consulted, and the front end is notified that the dynamic output needs to be updated. The data associated with x
is then deleted. Essentially the system forgets all about the dynamic output, and subsequent assignments in the loop incur absolutely no speed penalty because of the existence of a dynamic output monitoring the value of x
Much later (on a computer time scale; only a fraction of a second on a human time scale) when the screen is next redrawn and the dynamic output containing the reference to x
is reevaluated, the connection between the dynamic output and the variable x
is noticed again, and the association is reestablished.
Meanwhile the loop has continued to run. The next time the assignment is done after the screen is updated, another notification will be sent to the front end, and the process repeats.
By default, dynamic outputs triggered by changes in variable values are updated no faster than twenty times per second (this rate can be changed with the SystemOption "DynamicUpdateInterval"
). In the previous example you will typically see the value jump by tens or hundreds of thousands with each update (more the faster your computer is), and the overall speed of the computation is slowed down by only a percent or two, nearly zero if you have a multiprocessor system.
You might expect that having a dynamic output monitoring the value of a symbol that is being changed rapidly in a tight loop would slow that loop down significantly. But the overhead is in fact zero-order in the rate at which the variable is changed, and in practice is usually minimal.
Dynamic outputs are only updated when they are visible on screen. This optimization allows you to have an open-ended number of dynamic outputs, all changing constantly, without incurring an open-ended amount of processor load. Outputs that are scrolled off-screen, above or below the current document position, will be left unexamined until the next time they are scrolled on-screen, at which point they are updated before being displayed. (Thus the fact that they stopped updating is not normally apparent, unless they have side effects, which is discouraged in general.)
Dynamic output can depend on things other than variables, and in these cases tracking is also done carefully and selectively.
This gives a rapidly updated display of the current mouse position in screen coordinates.
As long as the output is visible on screen, there will be a certain amount of CPU activity any time the mouse is moved, because this particular dynamic output is being redrawn immediately with every movement of the mouse. But if it is scrolled off-screen, the CPU usage will vanish.
Normally, dynamic output is updated whenever the system detects any reason to believe it might need to be (see "Automatic Updates of Dynamic Objects"
for details about what this means). Refresh
can be used to modify this behavior by specifying explicitly what should or should not trigger updates.
This updates when either slider is moved.
with a TrackedSymbols
option can be used to specify a list of those symbols that should be tracked, with all other reasons for updating being ignored.
This updates only when x
changes, ignoring changes in y
When you move the second (y
) slider, nothing happens, but when you move the first slider, the expression is updated to reflect the current value of both variables. You might say that after moving the second slider, the dynamic output is wrong, since it does not reflect the current state of the system. But that is essentially the whole reason for the existence of the Refresh
command. It allows you to override the system's mandate to always update dynamic output any time it is potentially out of date.
The setting TrackedSymbols->Automatic
can be used to track only those symbols that occur explicitly (lexically) in the expression given in the first argument to Refresh
. For example, if you use a function that depends on a global variable that does not occur lexically inside Refresh
, changes to the value of the global variable will not cause updating, when normally they would.
can also be used to cause updates at regular time intervals. It is important to understand that this is not
a feature that should be used lightly. It is fundamental to the design of Dynamic
that it does not need to update on any fixed schedule, because it simply always updates immediately whenever doing so would be useful. But there are some situations where this either cannot, or just unfortunately does not, happen.
One potentially vexing case is RandomReal
. Every time you evaluate RandomReal
, you get a different answer, and you might think that Dynamic[RandomReal]
should therefore constantly update itself as fast as possible. But this would normally not be useful, and would in fact have negative consequences for a number of algorithms that use randomness internally (e.g., a Monte Carlo integration inside Dynamic
should probably not update constantly simply because it will, in fact, give a slightly different answer each time).
For this reason, RandomReal
is not "ticklish," in the sense that it does not trigger updates. If you want to see new random numbers, you have to use Refresh
to specify how frequently you want the output updated. Another example of non-ticklish functions are file system operations.
This gives you a new number every second.
This is not updated automatically.
In the unlikely event that the file containing the BasicMathInput
palette changes size, this Dynamic
will not be updated. If you want to monitor the size of a file, you need to use Refresh
to specify a polling interval. (On sufficiently advanced operating systems it would theoretically be possible for Mathematica
to efficiently receive notifications of file system activity, and future versions of Mathematica
might in fact update such expressions automatically. As with other Dynamic
expressions, automatic correctness is always the goal.)
Finally, several functions you might think would trigger dynamic updates in fact do not: for example, DateList
. As with RandomReal
, it would cause more trouble than it is worth for these functions to automatically trigger updates, and Refresh
can trivially be used to create clock-like objects. The function Clock
is intended specifically as a time-based function that is
This updates approximately every second.
This updates without an explicit Refresh
In the examples above, Refresh
is always the outermost function inside Dynamic
. You might almost wonder why its options are not simply options to Dynamic
. But in fact it is often important to place Refresh
as deeply in the expression as possible, especially if it specifies a time-based updating interval.
When the checkbox is checked, Refresh
is causing frequent updating of the clock, and CPU time is being consumed to keep things up-to-date. When the checkbox is unchecked, however, the Refresh
expression is no longer reached by evaluation, the output remains static, and no CPU time is consumed. If Refresh
were wrapped around the whole expression inside Dynamic
, CPU time would be consumed constantly, even if the clock were not being displayed. The words "No clock" would be constantly refreshed, pointlessly. (This refreshing is not visible; there is no flicker of the screen, but CPU time is being consumed nevertheless.)
expressions can be nested, and the system takes great care to update them only when necessary. Particularly when the contents of a Dynamic
contain further interactive elements, it is important to keep track of what will stay static and what will update, when a given variable is changed.
The position of the first slider determines the number of sliders underneath it, and each of those sliders in turn is connected to the value of one element of a list of data. Because the number of sliders is variable, and changes dynamically in response to the position of the first slider, the table that generates them needs to be inside Dynamic
The example above works, but now suppose you want to display the value of each number in the list next to its slider.
You might at first try this.
Now any time you click one of the lower sliders, it moves only one step, then stops. The problem is that the data[[i]]
expressions in the second column of the grid are creating a dependency in the outer Dynamic
on the values in data
As soon as data
changes, the contents of the outer Dynamic
, including the slider you are trying to drag, are destroyed and replaced with a nearly identical copy (in which the displayed value of one of the data[[i]]
has been changed). In other words, the act of dragging the slider destroys it, preventing any further activity.
The solution to this is to prevent the outer Dynamic
from depending on the value of data, by making sure that all occurrences of data in the expression are wrapped in Dynamic
Now you can drag any of the sliders and see dynamically updated values. This works because the outer Dynamic
now depends only on the value of n
, the number of sliders, not on the value of data
. (Technically this is because Dynamic
: when it is evaluated, the expression in its first argument is never touched by evaluation, and therefore no dependencies are registered.)
When building large, complex interfaces using multiple levels of nested Dynamic
expressions, these are important issues to keep in mind. Mathematica
works hard to do exactly the right thing even in the most complex cases. For example, the output of Manipulate
consists of a highly complex set of interrelated and nested Dynamic
expressions: if the dependency tracking system did not work correctly, Manipulate
would not work right.
Synchronous versus Asynchronous Dynamic Evaluations
consists of two separate processes, the front end and the kernel. These really are separate processes in the computer science sense of the word: two independent threads of execution with separate memory spaces that show up separately in a CPU task monitor.
The front end and kernel communicate with each other through several MathLink
connections, known as the main link, the preemptive link, and the service link. The main and preemptive links are pathways by which the front end can send evaluation requests to the kernel, and the kernel can respond with results. The service link works in reverse, with the kernel sending requests to the front end.
The main link is used for Shift+Enter
evaluations. The front end maintains a queue of pending evaluation requests to send down this link. When you use Shift+Enter
on one or more input cells, they are all added to the queue, and then processed one by one. At any one time, the kernel is only aware of a single main link evaluation, the one it is currently working on (if any). In the meantime, the front end remains fully functional; you can type, open and save files, and so on. There is no arbitrary limit on how long a main link evaluation can reasonably take. People routinely do evaluations that take days to complete.
The preemptive link works the same way as the main link in the sense that the front end can send an evaluation to it and get an answer, but it is administered quite differently on both ends. On the front end side, the preemptive link is used to handle normal Dynamic
updates. There is no queue; instead, the front end sends one evaluation at a time and waits for the result before continuing with its other work. It is thus important to limit preemptive link evaluations to a couple of seconds at most. During any preemptive link evaluation, the front end is completely locked up, and no typing or other actions are possible.
On the kernel side, evaluation requests coming from the preemptive link are given priority over evaluations from the main link, including the current running main link evaluation (if any). If an evaluation request comes from the preemptive link while the kernel is processing a main link evaluation, the main link evaluation is halted at a safe point (usually within microseconds). The preemptive link evaluation is then run to completion, after which the main link evaluation is restarted and allowed to continue as before. The net effect is similar to, though not the same as, a threading mechanism. Multiple fast preemptive link evaluations can be executed during a single long, slow main link evaluation, giving the impression that the kernel is working on more than one problem at a time.
Preemptive link evaluations can change the values of variables, including those being used by a main link evaluation running at the same time. There is no paradox here, and the interleaving is done in a way that is entirely safe, though it can result in some fairly peculiar behavior until you understand what is going on.
For example, evaluate this to get a slider.
Then evaluate this command, and during the ten seconds it takes to finish, drag the slider around randomly.
You will not see anything happening (other than the slider moving) but when the second evaluation finishes, you will see that it has recorded ten different values of x
, representing the positions the slider happened to be at during the ten points at which x
was evaluated to build the list.
normally uses the preemptive link for its evaluations. Evaluation is synchronous, and the front end locks up until it is finished. This is unavoidable in some cases, but can be suboptimal in others. By setting the option SynchronousUpdating->False
, you can tell the front end to use the main link queue, rather than the preemptive link. The front end then displays a gray box placeholder until it receives the response from the kernel.
In this case, the default (synchronous) update is appropriate because the front end needs to know the result of evaluating the Dynamic[x]
for drawing with the correct font size.
Here, the output cell is drawn before the second dynamic expression finishes. A gray box placeholder persists for one second until the result is known. Reevaluate the example to see the gray box again.
Clicking the slider will update the display with a delay of between one and ten seconds. Notice that the cell bracket is outlined, just as if the cell were being Shift+Enter
evaluated. This is an indication that the evaluation is queued, and that you can continue with other work in the front end while the evaluation is progressing.
Asynchronous updating is useful for displaying full Dynamic subexpressions when it is possible to draw a screen around them and fill in their value later, in much the same way a web browser draws text around an image that is inserted later when it finishes downloading.
Why not always use asynchronous Dynamic
expressions? There are several reasons. First, they are queued so that, by definition, they do not operate while another Shift+Enter
evaluation is underway. This is not the case for normal (synchronous) updates.
A synchronous Dynamic
updates smoothly even if the Pause
command above is running.
Also, many controls need to be synchronous in order to be responsive to mouse actions. Making them asynchronous may cause potentially strange interactions with other controls.
Here is a problematic example.
Move the slider around rapidly, and you will end up with a choppy, distorted sine wave, because the value of n
changed during the evaluation of the Table
command. This is the correct, expected behavior, but it is probably not what you wanted.
This problem does not occur if you use synchronous Dynamic
expressions, generally does not happen with DynamicModule
local variables, and can be avoided by storing the value of any potentially changing variables into a second variable before starting the asynchronous evaluations.
ControlActive and SynchronousUpdating→Automatic
As a general rule, if you have a Dynamic
that is meant to respond interactively to the movements of a slider or other continuous-action control, it should be able to evaluate in under a second, preferably well under. If the evaluation takes longer than that, you are not going to get satisfactory interactive performance, whether the Dynamic
is updating synchronously or asynchronously.
But what if you have an example that simply cannot finish evaluating fast enough, yet you want to be able to make it respond to a slider? One option is to use asynchronous updating and simply accept that you will not get real-time interactive performance. If that is what you want to do, setting ContinuousAction->False
in the slider or other control is a good idea; that way you get only one update after the control is released, avoiding the starting up of potentially lengthy evaluations in the middle of a drag, before you have arrived at the value you want to stop at.
The cell bracket becomes outlined, indicating evaluation activity, only after you release the slider.
Another, much better solution is to provide a fast-to-compute preview of some sort during the interactive control dragging operation, then compute the full, slow output when the control is released. Several features exist specifically to support this.
The first is the function ControlActive, which returns its first argument if a control is currently being dragged, and its second argument if not. Unlike Dynamic, ControlActive is an ordinary function that evaluates in the kernel, returning one or the other of its arguments immediately. It can be embedded inside functions or option values.
The second feature is an option setting SynchronousUpdating->Automatic
, which makes the Dynamic
synchronous when a control is being dragged, and asynchronous when the control is released. Together, these two features can be used to implement a fast, synchronously updated display to be used while a control is being dragged, along with a slower, asynchronously updated display when it is released.
The displayed text changes depending on whether or not the slider is being dragged.
A simple number is displayed, synchronously, while the slider is being dragged, and when it is released, a graphic is generated asynchronously.
This example shows that the front end can remain responsive no matter how long the final display takes to compute and that the preview and the final display can be completely different.
Of course, in most cases, you will want a preview that is some kind of reduced, thinned out, skeletal, or other elided form of the final display. Then the crude form can be fast enough to give a smooth preview, and the computation of the final version, even if it takes awhile, does not block the front end. In fact, this behavior is so useful that it is the default in Plot3D and other plotting functions.
This displays a 3D plot with a very small number of plot points while the control is being dragged and then refines the image with a large number of plot points when the control is released.
By default, Plot3D
produces a similar preview, though with a somewhat less extreme spread of quality.
You may have noticed one subtlety. When the output of either of the above three examples is first placed in the notebook, you see a crudely drawn (control-active state) version, followed shortly thereafter by a refined (control-inactive) version. This is intentional: the system is providing a fast preview so you see something rather than just a gray rectangle. The first update is done synchronously, just as if a control were being dragged.
This preview-evaluation behavior is examined in more detail in the next section.
ImageSizeCache in Dynamic
ImageSizeCache is an option to Dynamic that specifies a rectangular size to be used in displaying a Dynamic whose value has not yet been computed. It is normally not specified in input, but is instead generated automatically by the front end and saved in files along with the Dynamic expression.
The interaction of ControlActive
, and ImageSizeCache
is subtle, complex, and very useful. The first two constructs are explained in ControlActive and SynchronousUpdating→Automatic
. The remaining part is explained here.
Note first that Dynamic expressions with the default value of SynchronousUpdating->True will never have a chance to use the value of their ImageSizeCache option, because they are always computed before being displayed, and, once computed, the actual image size will be used.
On the other hand, Dynamic
expressions with SynchronousUpdating→False
will be displayed as a gray rectangle while they are being computed for the first time. In that case, the size of the rectangle is determined by the value of the ImageSizeCache
option. This allows the surrounding contents of the notebook to be drawn in the right place, so that when the Dynamic
finishes updating, there is no unnecessary flicker and shifting around of the contents of the notebook. (Users of HTML will recognize this as the analog of the width and height parameters of the img
It is generally not necessary to specify the ImageSizeCache
option explicitly, because the system will set it automatically as soon as the value of the Dynamic
is computed successfully. (The computed result is measured, and the actual size copied into the ImageSizeCache
option.) This automatically computed value is preserved if the Dynamic
output is saved in a file.
Consider the following input.
When the input expression is evaluated, a small gray rectangle appears; because this Dynamic
has never been evaluated, there is no cache of its proper image size, and a default small size is used.
Three seconds later, the result arrives, and the dynamic output is displayed. At this point an actual size is known, and is copied to the ImageSizeCache
option. You can see the value by clicking anywhere in the output cell and choosing from the menu. (This shows you the underlying expression representing the cell, exactly as it would appear in the notebook file if you were to save this cell.) Note the presence of an ImageSizeCache
Now type a space in some innocuous place in the raw cell expression (to force a reparsing of the cell contents), and choose again to reformat the cell. This time you will see a gray rectangle the size of the final output for three seconds, followed by the proper output. This is also what you would see if you opened a notebook containing previously saved, asynchronous dynamic output.
The behavior of the setting SynchronousUpdating->Automatic
is similar, but subtly different. As we saw in the examples in "ControlActive and SynchronousUpdating→Automatic"
, with the Automatic
setting, a synchronous preview-evaluation is done when the output is first placed, to provide a (hopefully) rapid display of the contents of the Dynamic
expression before the slower, asynchronous value is computed. Because the first evaluation is synchronous, no gray rectangle is ever displayed.
But this preview evaluation is done only if the ImageSizeCache
option is not present. A Dynamic
and an ImageSizeCache
option specifying explicit dimensions will not do a synchronous preview evaluation, and will instead display a gray rectangle (of the correct size) pending the result of the first asynchronous evaluation.
This may seem like baffling behavior at first, until you consider the practical effect of it. Generally speaking, Dynamic
expressions will always have an ImageSizeCache
option (created automatically by the front end) except for the very first time they appear, when they are originally placed as output from an evaluation. Any time they are opened from a file they will have a known, cached size.
, which accounts for the vast majority of dynamic outputs, the default setting is SynchronousUpdating->Automatic
and the described behavior lets the output show up cleanly with a preview image in place when it is first generated. When a file containing dozens of Manipulate
outputs is opened, you will get a useful behavior that is familiar from web browsers: the text displays immediately, and graphics (and other dynamic content) fill in later as fast as they are able. So you can scroll through a file rapidly, without any delay associated with precomputing potentially many preview images before the first page of the file can be displayed.
If the initial evaluations when the Manipulate
output was first placed were not synchronous, there would be flicker and resizing/shifting of the surroundings, because the size would not be known. But when the Manipulate
output is opened from a file, the size is known, and the final output can be placed smoothly without flicker.
One-Sided Updating of ControlActive
After evaluating in the kernel, ControlActive can trigger an update of the Dynamic containing it, but in a highly asymmetric fashion, only when it is going from the active to the inactive state. When making a transition in the other direction, from inactive to active, ControlActive does not trigger any update on its own.
The reason for this somewhat unusual behavior is that ControlActive is a completely global concept. It returns the active state if any control anywhere in Mathematica is currently being dragged—even controls that have nothing to do with a particular Dynamic that happen to contain a reference to ControlActive. If ControlActive caused updates on its own, then as soon as you clicked any control, all Dynamic expressions containing references to ControlActive (e.g., a default dynamic Plot3D output) would immediately update, which would be entirely pointless. Instead, only those outputs that have some other reason for updating will pick up the current value of ControlActive.
On the other hand, when the control is released, it is desirable to fix up any outputs that were drawn in control-active form, to give them their final polished appearance. Thus, when ControlActive is going into its inactive state, it needs to, on its own, issue updates to any Dynamic expression that may have been drawn in the active state.
Dragging the slider does not change the Active/Inactive display because ControlActive
does not trigger updates on its own.
This Active/Inactive display updates because x
in the dynamic output changes.
Watch carefully what happens when you click the slider. If you click and hold the mouse without moving it, the display will remain Inactive
. But as soon as you move it, the display updates to Active
. This is happening because x
changed, causing the Dynamic
as a whole to update, thus picking up the current state of ControlActive
Now carefully release the mouse button without moving the mouse. Note that the display does revert to Inactive
even though x
has not changed.
The variables declared in a DynamicModule
are localized to a particular rectangular area within one cell in a notebook. There are situations in which it is desirable to extend the scope of such a local variable to other cells or even other windows. For example, you might want to have a button in one cell that opens a dialog box that allows you to modify the value of a variable declared in the same scope as the button that opened the dialog.
This can be done with one of the more surreal constructs in Mathematica
, a DynamicModule
accepts the option DynamicModuleParent
, whose value is a NotebookInterfaceObject
that refers to another DynamicModule
anywhere in the front end. For purposes of variable localization, the DynamicModule
with this option will be treated as if it resided inside the one referred to, regardless of where the two actually are (even if they are in separate windows).
The tricky part in setting up such a wormhole is getting the NotebookInterfaceObject
necessary to refer to the parent DynamicModule
. This reference can be created only after the DynamicModule
has been created and placed as output, and it is valid only for the current session.
To make the process easier, and in fact avoid all reference to explicit NotebookInterfaceObject
also accepts the option InheritScope
, which automatically generates the correct value of the DynamicModuleParent
option to make the new DynamicModule
function as if it were inside the scope of the DynamicModule
from which it was created. This is confusing, so an example is in order.
Evaluate this to create an output with a +
button and a number.
Clicking the + button increments the value of a DynamicModule local variable, which is displayed at the end of the output. To decrement the number you have to click the Make - Palette button, which creates a new (very small) floating palette window containing a - button.
button is living in a wormhole created by the InheritScope
option of the DynamicModule
containing it. Clicking the button decrements the value of a local, private variable in the scope of a distant DynamicModule
in another window.
can be used only when the code creating the second DynamicModule
is executed from inside a button or other dynamic object located within the first DynamicModule
. By using DynamicModuleParent
explicitly, it is possible to link up arbitrary existing DynamicModule
s, but doing so is tricky, and beyond the scope of this document.