Dynamic 在网格中指定局部动态

Dynamic 在网格中指定局部动态,dynamic,wolfram-mathematica,wrapper,Dynamic,Wolfram Mathematica,Wrapper,我想以不同的方式动态更新网格的特定部分。考虑下面的玩具例子:我有两行:一个必须逐个更新(a,b,c),因为这些符号依赖于不同的触发器;第二行依赖于单个触发器(show),该触发器允许显示/隐藏某些数据 现在我知道我可以将整个网格结构包装成动态,甚至可以指定要跟踪的符号,因此这个示例实现了我想要的: Checkbox[Dynamic[show]] test = {0, 0}; Dynamic[Grid[{{Dynamic@a, Dynamic@b, Dynamic@c}, If[show,

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

现在我知道我可以将整个
网格
结构包装成
动态
,甚至可以指定要跟踪的符号,因此这个示例实现了我想要的:

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

尽管出于某些原因,我希望有一个本地指定的
动态
,它只应用于
网格的第二行

对于那些想知道这会是什么不光彩的情况的人,只要想象一下以下情况:
show
a
b
c
中的任何一个中使用,这些我不想在
show
发生变化时更新,它们的变化取决于其他触发器。为什么不从第一行的符号中删除
show
?想象一下,我不能,因为
show
存在于
a
b
c
中使用的函数中,而这个函数我无法轻松访问

当然,将
If
的第一个参数包装到
Dynamic
中不会有帮助,因为
网格本身或其任何单元格都不会变成动态的:

Grid[{
  {Dynamic@a, Dynamic@b, Dynamic@c},
  If[Dynamic@show, Prepend[test, "test:"], {}]
  }, Frame -> All]
此外,将行包装到
动态
中会使给定行无效,因为它不再具有头
列表

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
进行3次评估,而不是仅评估1次

Grid[{
  {Dynamic@a, Dynamic@b, Dynamic@c},
  Dynamic[If[show, #, ""]] & /@ Prepend[test, "test:"]
  }, Frame -> All]

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

这里是一个使用实验性
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,而不是在整个网格上使用Dynamic,这正是您想要的:

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

顺便说一句,我刚刚读了telefunkenvf14的一篇文章,其中提到了这个软件包和这个函数,我不知道,当我看到这个函数时,我想起了这个问题,我认为应该可以使用这个函数来解决这个问题

另外,我需要在正确放置网格行方面做更多工作

更新(1)

我不知道如何将最后一行拼接到网格中的列上。这很奇怪,因为它有列表头,但它不会遍历所有列。它只会进入第一个单元。试过序列、左跨等等,但运气不好。也许有人能猜出这部分

以下是我目前的试验:

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]

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

解决方案的线索可在文档中
项目
可能问题部分找到:

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

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

Needs["Experimental`"];
row = {"", "", ""}; 
updateRow[x_, v_] := row = If[v, Prepend[test, "test:"], {"", "", ""}];
Experimental`ValueFunction[show] = updateRow;
所需的第二个更改是包装
Dynamic@row

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

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

所以你需要一个解决方案,其中1。有一个网格有两排2。两行取决于
显示
3。但是当
show
更改时,只需更新第二行。我做对了吗?你能解释一下为什么对
If
进行三次评估是不可取的吗?如果在
中进行测试,费用是否昂贵?我们可能会想出一种方法,对测试进行一次评估,并将结果存储到一个变量中,然后该变量控制三个
If
s。我相信如果你把整件事都包装起来,那么你就无法避免更新
a、b、c
,但我不确定!是的,您对需求的看法是正确的,当然,If中的测试并不太昂贵,目前代码是这样运行的(映射If)。然而,还有一件事更成问题,我正试图指出这一点。在您的第一个示例中是否存在剪切粘贴错误?它没有给出上一个示例的输出。kguler:你说得对,我在复制粘贴时忘了更新代码。谢谢,请参阅编辑。很高兴看到我浪费在文档黑暗空间的时间得到了很好的利用。谢谢你的提醒德纳瑟:这不完全是我想要的,但这很好地补充了我迄今为止尝试过的所有方法。问题基本上是更新网格中的一行,这样该行的内容就不会被拆分、分离、查看、剖析等等。我想说的是,第二行仍然是手动拆分的。我想我现在确信,除了将动态包裹在整个网格结构上,或者将网格拆分为两个网格并只更新第二个网格之外,没有简单明了的解决方案。@Istvan,我同意。我希望你的第一个和最后一个解决方案是最干净的。