动态交互问题

17

我想要有两个面板,左侧显示一个图形和两个定位器,右侧显示在由定位器定义的区域内放大的版本。

我尝试过:

ClearAll[mndpt];
mndpt = Compile[{{c, _Complex}, {maxiter, _Integer}},
   Module[{z, iters},
        iters = 0.;
        z = c;
            While[(iters < maxiter) && (Abs@z < 2),
                iters++;
                z = z^2 + c];
        Sqrt[iters/maxiter]],
   {{z, _Complex}},
   CompilationTarget \[Rule] "C",
   RuntimeOptions \[Rule] "Speed"];

并执行

Manipulate[
 Grid[
  {{DensityPlot[mndpt[x + y*I, 200],
        {x, -2, 1}, {y, -1.5, 1.5},
        PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80, 
     ColorFunction \[Rule] "Rainbow"],
    DensityPlot[mndpt[x + y*I, 200],
        Dynamic@{x, p1[[1]], p2[[1]]}, Dynamic@{y, p1[[2]], p2[[2]]},
        PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80, 
     ColorFunction \[Rule] "Rainbow"]}}],
 {{p1, {-1, -1}}, Locator}, {{p2, {0, 1}}, Locator}]
右侧面板无法正常工作: enter image description here 我的问题是,为什么会这样?如您所见,它抱怨" DensityPlot::pllim: Range specification {x,-1,0} is not of the form {x, xmin, xmax}。",这让我感到困惑。实际上,我一直感到困惑。发生了什么?一些范围问题?评估问题?我该如何解决?这可能很简单,但我从来没有真正理解过这个前端东西。
编辑:事实证明,这个问题是由于我自己愚蠢的短暂增加而引起的。正如Simon在评论中指出的那样,删除我盲目添加的两个 Dynamics(以使其正常工作)可以使一切正常。也就是说,
    Manipulate[
 Grid[
  {{DensityPlot[mndpt[x + y*I, 200],
        {x, -2, 1}, {y, -1.5, 1.5},
        PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80, 
     ColorFunction \[Rule] "Rainbow"],
    DensityPlot[mndpt[x + y*I, 200],
        {x, p1[[1]], p2[[1]]},{y, p1[[2]], p2[[2]]},
        PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80, 
     ColorFunction \[Rule] "Rainbow"]}}],
 {{p1, {-1, -1}}, Locator}, {{p2, {0, 1}}, Locator}]

做了正确的事情:

enter image description here

那么,谁知道为什么前几次我做的时候它没起作用。

另一方面,在原始情况下的消息,即“DensityPlot :: pllim:范围说明{x,-1,0}不是{x,xmin,xmax}的形式。”更加令人费解。我想Leonid已经在评论中解释过(简而言之,请尝试ClearAttributes [Dynamic,ReadProtected]然后 ?? Dynamic ,你会看到有一个定义 Dynamic /:MakeBoxes [ BoxForm`x $ _ Dynamic,StandardForm]:= 等)。由于我的前端编程理解很少,因此我不会在这里尝试解释它,所以如果有人发表回答来解释它,那将不胜感激。


5
去掉这两个 Dynamic,一切就能正常运行。 - Simon
1
@Simon 哇,谢谢!实际上我把它们放在那里是因为“它不起作用”,然后我随机添加东西直到它起作用。谁知道我做了什么......请把你的评论作为答案,这样我就可以接受它。此外,如果你有任何关于 Dynamic 为何会弄乱它的想法,我想知道。 - acl
1
@acl Dynamic(和许多其他命令一样)通过UpValues重新定义了MakeBoxes(一旦从Dynamic中删除ReadProtected属性,您就可以看到它们)。这应该会影响使用和错误消息。 - Leonid Shifrin
3
如果Simon回答这个问题,我会很高兴,因为他之前回答过这个问题。然后,他可以在回答中加入我们讨论的某些部分,或者我可以通过编辑他的回答来完成。 - Leonid Shifrin
@Leonid:你想写答案吗?你的评论给了我足够的线索来解决问题,但也表明你比我更了解这个问题。 (但是,对于我发布的大多数SO答案而言,这可能是真的)。我只是认为额外的“Dynamic”是不必要的,因为在“Manipulate”的整个第一个参数中自动包装了“Dynamic”(或类似的东西)。 - Simon
显示剩余11条评论
1个回答

5
如问题的评论中所讨论的那样,如果在第二个DensityPlot的范围内删除Dynamic,则代码正常工作。在Manipulate的主体中通常不需要使用Dynamic,因为它会自动包装在动态结构中。虽然可以使用在Manipulate中的Dynamic来更精细地控制表达式的哪些部分更新,但这对于使用Manipulate中的Dynamic可能是有用的。
错误产生的原因是绘图的范围应该是{x,xmin,xmax}的形式,其中x是一个Symbol,xmin和xmax是数字。在列表周围包装Dynamic会更改头文件并破坏图​​​​​。
错误不容易发现的原因是错误消息有点令人困惑:

范围规范{x,-1,0}不是{x,xmin,xmax}的形式。

表面上看起来很疯狂,但一旦你意识到(正如Leonid所指出的),Dynamic是一个包装器,它具有一个MakeBoxes定义,使其在输出到笔记本时变得不可见。要查看这个,请看

In[1]:= FormatValues[Dynamic]
Out[1]= {HoldPattern[MakeBoxes[BoxForm`x$_Dynamic, StandardForm]] :> (DynamicModule; 
           DynamicDump`ControlToBoxes[BoxForm`x$, StandardForm]), 
        <<snip: same but for TraditionalForm>>}

然后,ControlToBoxes 依次创建一个 DynamicBox 对象。这也可以通过输入 Dynamic[x] 并使用单元格菜单或快捷方式到 Show Expression 的产生的输出单元格来查看 - 您还可以查看错误消息的基础表达式并在那里查看 DynamicBox 构造。也可以 Unprotect 并删除 DynamicMakeBoxes 定义,但这会破坏 Mathematica 中的大部分动态功能...


最终,这是我的代码版本:
mndpt = Compile[{{c, _Complex}, {maxiter, _Integer}},
   Module[{z = c, iters = 0.0},
    While[(iters < maxiter) && (Abs@z < 2), iters++; z = z^2 + c];
    Sqrt[iters/maxiter]], CompilationTarget -> "C", 
   RuntimeOptions -> "Speed"];

opts = Sequence[PlotPoints -> 80, ColorFunction -> "Rainbow", 
   ImageSize -> Medium, ImagePadding -> {{30, 5}, {20, 5}}];

fixed = DensityPlot[mndpt[x + y*I, 200], {x, -2, 1}, {y, -1.5, 1.5}, 
   PlotPoints -> 120, Evaluate[opts]];

Manipulate[Grid[{{fixed, DensityPlot[mndpt[x + y*I, 200],
   {x, p[[1, 1]], p[[2, 1]]}, {y, p[[1, 2]], p[[2, 2]]}, Evaluate[opts]]}}],
 {{p, {{-1, -1}, {0, 1}}}, Locator, ContinuousAction -> False}]

output of the above


1
巧合的是,我在你提交后几乎立刻看到了这个。看起来我在你提交14秒后就点赞并接受了你的答案,我猜这一定是一个记录! - acl
1
@acl:这刚给我赢得了复活徽章 - 懒人有好报! - Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接