高级动态功能
| Module 与 DynamicModule | 同步与异步动态计算 |
| 前端对 DynamicModule 变量值的所有权 | ControlActive 和 SynchronousUpdatingAutomatic |
| 动态对象的自动更新 | Dynamic 中的 ImageSizeCache |
| 刷新 | ControlActive 的单边更新 |
| 嵌套刷新 | DynamicModule 虫洞 |
| 嵌套动态 |
Module[{x}, x]Module[{x}, Dynamic[x]]Table[Module[{x = .5}, {Slider[Dynamic[x]], Dynamic[x]}], 2]Table[DynamicModule[{x = .5}, {Slider[Dynamic[x]], Dynamic[x]}], 2]Module[{x = 2, y, z},
x = 4;
y = x^2;
x = 8;
z = x^3;
]x = 0;Table[Slider[Dynamic[x]], 500]DynamicModule[{x = 0}, Table[Slider[Dynamic[x]], 500]]Dynamic[a + b + c]Dynamic[If[a, b, c]]Dynamic[x]Do[x, {x, 1, 5000000}]Dynamic[MousePosition[]]DynamicModule[{x, y}, Column[{
Slider[Dynamic[x]],
Slider[Dynamic[y]],
Dynamic[{x, y}]}]]DynamicModule[{x, y}, Column[{
Slider[Dynamic[x]],
Slider[Dynamic[y]],
Dynamic[Refresh[{x, y}, TrackedSymbols -> {x}]]}]]Dynamic[Refresh[RandomReal[], UpdateInterval -> 1]]Dynamic[FileByteCount[FileNameJoin[{$InstallationDirectory, "SystemFiles", "FrontEnd", "Palettes", "ClassroomAssistant.nb"}]]]Dynamic[Refresh[DateList[], UpdateInterval -> 1]]Dynamic[Clock[{1, 10}]]DynamicModule[{showclock = True}, {Checkbox[Dynamic[showclock]], Dynamic[If[showclock, Refresh[DateList[], UpdateInterval -> 0.05], "No clock"]]}]DynamicModule[{n = 5, data = Table[RandomReal[], 20]},
Column[{
Slider[Dynamic[n], {1, 20, 1}], Dynamic[Column[Table[With[{i = i}, Slider[Dynamic[data[[i]]]]], {i, n}]]]}]]DynamicModule[{n = 5, data = Table[RandomReal[], 20]},
Column[{
Slider[Dynamic[n], {1, 20, 1}],
Dynamic[Grid[Table[With[{i = i},
{Slider[Dynamic[data[[i]]]], data[[i]]}], {i, n}]
]]}]]DynamicModule[{n = 5, data = Table[RandomReal[], 20]},
Column[{
Slider[Dynamic[n], {1, 20, 1}],
Dynamic[Grid[Table[With[{i = i},
{Slider[Dynamic[data[[i]]]], Dynamic[data[[i]]]}], {i, n}]
]]}]]Slider[Dynamic[x]]Table[Pause[1];x, 10]DynamicModule[{x = 12}, {Slider[Dynamic[x], {10, 100}], Style["Hello", FontSize -> Dynamic[x]]}]DynamicModule[{n = 1}, Column[{Slider[Dynamic[n], {1, 10}], Dynamic[Pause[n];n, SynchronousUpdating -> False]}]]Pause[20]DynamicModule[{n = 1}, Column[{Slider[Dynamic[n], {1, 10}], Dynamic[n]}]]n = 1;
Column[{Slider[Dynamic[n], {1, 10}], Dynamic[Graphics[Line[Table[{x, Sin[n x]}, {x, 0, 2Pi, 0.0001}]]], SynchronousUpdating -> False]}]n = 1;
Column[{Slider[Dynamic[n], {1, 10}], Dynamic[Module[{n1 = n}, Graphics[Line[Table[{x, Sin[n1 x]}, {x, 0, 2Pi, 0.0001}]]]], SynchronousUpdating -> False]}]DynamicModule[{n = 1}, Column[{Slider[Dynamic[n], {1, 10}, ContinuousAction -> False], Dynamic[Pause[n];n, SynchronousUpdating -> False]}]]DynamicModule[{n = 1}, Column[{Slider[Dynamic[n], {1, 10}], Dynamic[{n, ControlActive["Active", "Not Active"]}]}]]DynamicModule[{n = 3}, Column[{Slider[Dynamic[n], {3, 1000, 1}], Dynamic[Graphics[ControlActive[Inset[n, {0, 0}], Line[Table[{{0, 0}, {Cos[t], Sin[t]}}, {t, 0., 2Pi, 2Pi / n}]]], ImageSize -> 300, PlotRange -> 1], SynchronousUpdating -> Automatic]}]]这个例子显出无论最后的显示需要多长的时间来计算前端都能保持有反应,并且预演和最后的显示可以是完全不一样的.
当然,在绝大多数情况下,你会希望预演是最终显示的某种缩小的,稀释的,骨架的,或其它省略的形式. 这样这个粗陋的形式能够足够快地给出一个平滑的预演,并且,最后版本的计算,即使需要花一些时间,不会妨碍前端. 实际上,这个行为非常有用以至于它是 Plot3D 和其它画图函数中的默认行为.
DynamicModule[{n = 1}, Column[{Slider[Dynamic[n], {1, 5}], Dynamic[Plot3D[Sin[n x y], {x, 0, 3}, {y, 0, 3}, PlotPoints -> ControlActive[10, 100], MaxRecursion -> 0], SynchronousUpdating -> Automatic]}]]DynamicModule[{n = 1}, Column[{Slider[Dynamic[n], {1, 5}], Dynamic[Plot3D[Sin[n x y], {x, 0, 3}, {y, 0, 3}], SynchronousUpdating -> Automatic]}]]Manipulate[Plot3D[Sin[n x y], {x, 0, 3}, {y, 0, 3}], {n, 1, 5}]ImageSizeCache(图象尺寸隐存)是对 Dynamic 的一个选项,它指定一个用来显示值还没有被计算的 Dynamic 的矩形的尺寸. 一般它不在输入中指定,相反是由前端自动地产生并且和 Dynamic 表达式一起保存在文件中.
首先注意带有 SynchronousUpdating->True(同步更新 -> 真)这个默认数值的 Dynamic 表达式永远不会有机会使用它们的ImageSizeCache 的选项的数值,因为它们总是在被显示之前被计算,而一旦被计算,就会用实际的图像尺寸.
Dynamic[Pause[3];Style["Hello", 100], SynchronousUpdating -> False]在内核中计算之后,ControlActive 能触发含有它的 Dynamic 的更新,但是这是以一个极度不对称的形式进行的,即只有从激活到未激活的状态时才进行. 当从另一个方向,即从未激活到激活进行转变时,ControlActive 本身不触发任何更新.
这种有些不寻常的行为的原因是 ControlActive 是一个完全全局的概念. 当 Wolfram 系统中任何地方的任何控件当前正在被拖拉时,它都返回激活状态,即使这些控件与碰巧包含 ControlActive 的参考 Dynamic 毫无关系. 如果 ControlActive 自身引起更新,那么一旦你点击任何控件,所有包含对 ControlActive 的参考的 Dynamic 表达式(例如,一个默认的动态 Plot3D 的输出)都将会立即更新,这完全是无意义的. 相反地,只有那些有某种其它原因需要更新的输出才会选用 ControlActive 当前的值.
另一方面,当控件被释放时,最好是完成任何以控件激活的形式绘制的输出,使它们具有最终完美的外貌. 因此,当 ControlActive 进入它的未激活状态时,它自身需要对任何可能在激活状态时绘制的 Dynamic 表达式发布更新.
DynamicModule[{x}, {Slider[Dynamic[x]], Dynamic[ControlActive["Active", "Inactive"]]}]DynamicModule[{x}, {Slider[Dynamic[x]], Dynamic[{x, ControlActive["Active", "Inactive"]}]}]DynamicModule[{x = 1}, {Button["+", ++x], Button["Make - Palette", CreatePalette[DynamicModule[{}, Button["-", --x], InheritScope -> True]]], Dynamic[x]}]点击那个“+”按钮让一个 DynamicModule 局部变量的值增加,显示在输出尾端. 来减小那个数,你必须点击 Make - Palette 按钮,这创建一个新的(很小的)漂浮的含有一个 - 按钮的面板窗口.