在网格中指定本地动态

时间:2012-01-10 16:11:49

标签: dynamic wolfram-mathematica wrapper

我想以不同的方式动态更新Grid的特定部分。请考虑以下玩具示例:我有两行:一行必须逐个更新( a b c ),如下所示:这些符号取决于不同的触发器;第二行依赖于一个允许显示/隐藏某些数据的单个触发器( show )。

现在我知道我可以将整个Grid结构包装到Dynamic中,甚至可以指定要跟踪的符号,因此这个示例可以满足我的需求:

Checkbox[Dynamic[show]]
test = {0, 0};
Dynamic[Grid[{{Dynamic@a, Dynamic@b, Dynamic@c}, 
   If[show, Prepend[test, "test:"], {}]}, Frame -> All],
 TrackedSymbols :> {show}]

Mathematica graphics

虽然出于某些原因我希望在本地指定Dynamic ,但这只适用于Grid的第二行。

对于那些想知道什么是不道德的情况的人,想象一下:show abc中的任何一个都会使用show我不想在show更改时更新,其更改取决于其他触发器。为什么不从第一行的符号中删除show?想象一下,我不能,因为abc中使用的函数中存在If,而且我无法轻松访问此函数。

当然,将Dynamic的第一个参数包装到Grid中对此没有帮助,因为Grid[{ {Dynamic@a, Dynamic@b, Dynamic@c}, If[Dynamic@show, Prepend[test, "test:"], {}] }, Frame -> All] 本身或其任何单元格都不会变为动态:

Dynamic

此外,将行换行到List会使给定行无效,因为它不再有头Grid[{ {Dynamic@a, Dynamic@b, Dynamic@c}, Dynamic@If[show, Prepend[test, "test:"], {}] }, Frame -> All]

Dynamic

在行上映射show不起作用,因为Grid[{ {Dynamic@a, Dynamic@b, Dynamic@c}, Dynamic /@ If[show, Prepend[test, "test:"], {}] }, Frame -> All] 未动态更新:

Dynamic[If[...]]

此外,将If包裹在列表成员周围工作,但现在我必须评估Grid[{ {Dynamic@a, Dynamic@b, Dynamic@c}, Dynamic[If[show, #, ""]] & /@ Prepend[test, "test:"] }, Frame -> All] 3次而不是1次。

Dynamic

想知道是否有任何解决方案可以通过在行上本地应用{{1}}包装来克服此特定问题。

2 个答案:

答案 0 :(得分:3)

以下是使用实验ValueFunction

的解决方案
show = True;
test = {0, 0};
Checkbox[Dynamic[show]]

现在在侧面编写自己的小动态更新功能

Needs["Experimental`"];
row = {};
updateRow[x_, v_] := row = If[v, Prepend[test, "test:"], {}];
ValueFunction[show] = updateRow;

现在制作网格,现在可以在每一行上使用Dynamic,而不是整个网格,这就是你想要的:

Grid[{
  {Dynamic@a, Dynamic@b, Dynamic@c},
  {Dynamic@row}
  },
 Frame -> All
 ]

enter image description here

PS。我刚刚通过telefunkenvf14阅读了这篇文章,提到了这个包和这个函数,我不知道,当我看到这个函数时,我记得这个问题,我认为应该可以使用该函数来解决这个问题

PS。我需要更多地正确地放置网格行....

<强>更新(1)

我无法想象如何将最后一行拼接在网格中的列上。这很奇怪,因为它有List头,但它不会遍历所有列。它只会进入第一个细胞。尝试过序列,SpanFromLeft等,但没有运气。也许有人可以把这部分搞清楚。

这是我目前的试用版:

Needs["Experimental`"];
row = {};
updateRow[x_, v_] := row = If[v, {"test:", 0, 0}, {}];
ValueFunction[show] = updateRow;
show = False;
Checkbox[Dynamic[show]]

f = Grid[{
   {Dynamic@a, Dynamic@b, Dynamic@c},
   List@Dynamic[row]
   },
  Frame -> All
  ]

它似乎应该是可行的。我现在看不出有什么问题......

<强>更新(2)

作为临时解决方案,我事先用力拆分第二排。这使我可以做我想做的事。不确定这是否符合OP规范(我的猜测是不符合),但这里是:

Needs["Experimental`"];
ra = 0;
rb = 0;
rc = 0;
updateRow[x_, v_] := 
 row = If[v, ra = "test:"; rb = 0; rc = 0, ra = ""; rb = ""; rc = ""]
ValueFunction[show] = updateRow;
show = False;
Checkbox[Dynamic[show]]

f = Grid[{
   {Dynamic@a, Dynamic@b, Dynamic@c},
   {Dynamic@ra, Dynamic@rb, Dynamic@rc}
   },
  Frame -> All]

enter image description here

答案 1 :(得分:1)

这实际上是对@ Nasser解决方案的评论,并建议修复以避免手动拆分第二行,但由于评论区域的空间限制,我将其作为答案发布。一旦纳赛尔确认它有效并将其纳入他的答案中,将很乐意将其删除。

解决方案的线索可在文档中Possible Issues的{​​{1}}部分找到:

  

如果Item不是支持Item的函数的子项中最顶层的项,则它将不起作用。

我用以下方式修改@ Nasser的解决方案。首先,我需要更改Item的定义,以便对row的两个值show的长度都相同。

row

需要进行的第二项更改是使用Needs["Experimental`"]; row = {"", "", ""}; updateRow[x_, v_] := row = If[v, Prepend[test, "test:"], {"", "", ""}]; Experimental`ValueFunction[show] = updateRow;

包装Dynamic@row的每个元素
Item

编辑:Grid[{{Dynamic@a, Dynamic@b, Dynamic@c}, {Item[Dynamic@row[[1]]], Item[Dynamic@row[[2]]], Item[Dynamic@row[[3]]]}}, Frame -> All] 包装器并不是真正需要的;它没有它也能正常工作:

Item