在网格中指定局部动态

发布于 2024-12-25 20:33:18 字数 1881 浏览 1 评论 0 原文

我想以不同的方式动态更新Grid的特定部分。考虑以下玩具示例:我有两行:其中一行必须逐一更新(abc),如下这些符号取决于不同的触发器;第二行取决于一个允许显示/隐藏某些数据的触发器(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}]

Mathematicagraphics

虽然由于某些原因我希望有一个本地指定的动态,即仅适用于第二行网格。

对于那些想知道这会是什么不合常理的情况的人,只需想象以下情况: show 用于 ab 中的任何一个>c,并且这些我不想在 show 更改时更新,它们的更改取决于其他触发器。为什么不从第一行的符号中删除 then 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 3 次,而不是 1 次。

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

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

I would like to update specific parts of a Grid dynamically in different ways. Consider the following toy example: I have two rows: one must be updated one-by-one (a, b, c), as these symbols depend on different triggers; the second row depends on one single trigger (show) that allows displaying/hiding some data.

Now I know that I can wrap the whole Grid structure into Dynamic, and even specify which symbols to track, thus this example does what I want:

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

Though for certain reasons I would like to have a locally specified Dynamic, that is only applied to the second row of the Grid.

For those who are wondering what ungodly situation would it be, just imagine the followings: show is used in any of a, b or c, and these I do NOT want to update when show is changing, their changes depend on other triggers. Why not remove then show from the symbols of the first row? Imagine, I can't, as show is present in a function that is used in a, b or c, and this function I cannot access easily.

Of course wrapping the first argument of If into Dynamic won't help here, as the Grid itself or any of its cells won't become dynamic:

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

Furthermore, wrapping a row into Dynamic makes the given row invalid, as it does not have head List anymore:

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

Mapping Dynamic over the row does not work either because show is not updated dynamically:

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

Also, wrapping Dynamic[If[...]] around list members work, but now I have to evaluate If 3 times instead of just 1.

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

Would like to know if there is any solution to overcome this particular problem by locally applying a Dynamic wrapper on a row.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怪我鬧 2025-01-01 20:33:18

这是使用实验 ValueFunction 的解决方案

show = True;
test = {0, 0};
Checkbox[Dynamic[show]]

现在在侧面编写您自己的小动态更新函数

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

现在制作网格,现在可以在每一行上使用动态,而不是在整个网格周围使用动态,这就是您想要的想要:

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

ps。我刚刚读了 telefunkenvf14 的一篇文章,提到了这个包和这个函数,我不知道,当我看到这个函数时,我想起了这个问题,我想应该可以使用这个函数来解决这个问题。

附:我需要在正确放置网格行方面做更多工作...

更新(1)

我不知道如何将最后一行拼接到网格中的列上。这很奇怪,因为它有列表头,但它不会遍历所有列。它只会进入第一个单元格。尝试过 Sequence、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
  ]

看来应该是可行的。我现在不明白问题是什么...

update(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]

Here is a solution using the Experimental ValueFunction

show = True;
test = {0, 0};
Checkbox[Dynamic[show]]

Now write your own little Dynamic update function on the side

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

Now make the Grid, and now can use Dynamic on EACH row, not around the whole Grid, which is what you wanted:

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

enter image description here

ps. I just read a post here by telefunkenvf14 that mentions this package and this function, which I did not know about, and when I saw this function, I remembered this question, and I thought it should be possible to use that function to solve this problem.

ps. I need to work more on placing the grid row correctly....

update(1)

I can't figure how to splice the final row over the columns in the grid. Which is strange, as it has List head, yet it won't go across all the columns. It will only go in the first cell. Tried Sequence, SpanFromLeft, and such, but no luck. May be someone can figure this part out.

Here is my current trial:

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
  ]

It seems it should be doable. I do not see what is the problem now...

update(2)

As a temporary solution, I split the second row by force before hand. This made it possible to do what I want. Not sure if this meets the OP specifications or not (my guess is that it does not), but here it is:

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

或十年 2025-01-01 20:33:18

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

解决方案的线索可以在文档中 ItemPossible Issues 部分中找到:

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

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

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

所需的第二个更改是用 Item 包装 Dynamic@row 的每个元素:

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

编辑:实际上并不需要 Item 包装器;没有它它也能工作:

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

This is actually a comment on @Nasser's solution and suggested fix to avoid manual splitting of the second row, but because of space limitations in the comment area, I post it as answer. Will be happy to delete it as soon as Nasser confirms that it works and incorporates it into his answer.

The clue to a solution is found in the Possible Issues section of Item in the documentation:

If Item is not the top-most item in the child of a function that supports Item, it will not work.

I use this to modify @Nasser's solution in the following way. First, I need to change the definition of row so that for both values of show the length of row is the same.

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

The second change needed is to wrap each element of Dynamic@row with Item:

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

Edit: Item wrapper is not really needed; it works just as well without it:

 Grid[{{Dynamic@a, Dynamic@b, Dynamic@c},
 {Dynamic@row[[1]], Dynamic@row[[2]], 
 Dynamic@row[[3]]}}, Frame -> All]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文