wolfram-mathematica - 在需要时在行之间的网格内添加分隔线的任何技巧

标签 wolfram-mathematica

要在网格中的行之间添加分隔线,我知道的一种方法是使用 Dividers选项。但这是在最后使用的,然后必须知道分隔符需要在其下方的行号。因此,对于大网格,我发现自己使用反复试验,直到找到正确的行号。然后当我稍后更改网格时,我必须再次反复试验以将分隔器放在正确的位置,以防它在我的更改后移动。

在这个例子中,有一个有 3 行的网格,我想在下面添加分隔线,比如第二行,所以我可以这样做:

Grid[{
  {1},
  {2},
  {3}
  }, Frame -> True, Dividers -> {All, 3 -> True}]

另一种方式,是把FalseTrue ,在我想要一个分隔符的正确顺序,像这样
Grid[{
  {1},
  {2},
  {3}
  }, Frame -> True, Dividers -> {All, {True, False, True, True}}]

enter image description here

如果我能做这样的事情就好了(就像一个人可以为 Manipulate 做的那样)(当然下面的这个在这里不起作用)
Grid[{
  {1},
  {2},
  Delimiter,
  {3}
  }, Frame -> True]

或者
Grid[{
  {1},
  {Item[2,Dividers->True]},
  {3}
  }, Frame -> True]

或者这样的事情。

这将使代码维护更容易。

我为此使用了 Item 等,但无法弄清楚。

任何人都知道一个技巧来做到这一点?

编辑:

顺便说一句,如果可能的话,这个技巧不仅适用于分频器。但是,能够执行许多其他网格选项(现在在网格级别完成)以及在项目级别完成将很有用。例如,如果我想在某行后添加一个额外的空格,那么按照我想要的速度说出来会更容易。此外,如果我想更改项目大小,更容易在现场进行,间距等也是如此。因此,当移动/复制整行或项目的代码时,它是自包含的,并将其连同其所有内容一起复制选项一起。

我认为现在这可能需要向 Mathematica Grid 添加一个新选项,以使其正常工作并与整个网格设计保持一致。

直到为 Mathematica 制作 GUI 构建器为止。

我发现我在编写演示时花费了超过 60% 的时间来使 GUI 适合并看起来正确。使用 GUI 构建器,我可以将这段时间花在算法上。当我使用 Matlab GUIDE 制作 GUI 时,我只需要不到 5% 的时间来制作一个类似的 GUI。

我希望 WRI 能够为 Mathematica 制作一个 GUI 构建器,如果你问我,我认为这将是 Mathematica 的杀手级应用。但没有人问我:)

编辑(2)

评论下面的巫师先生不错的解决方案。
我主要希望这个功能用于我用来为 Manipulate 布局控件的网格。 .这是一个简单的例子:
Manipulate[x,

 Grid[{
   {Control[{{x, 0, "x"}, 0, 10, 1}]},
   {Control[{{y, 0, "y"}, 0, 10, 1}]}
   }, Frame -> None, Dividers -> {None, {False, True, False}}
  ]
 ]

enter image description here

(我必须使用 Grid 来设置控件)。我不能在这里使用函数调用。我无法使用下面的向导解决方案编写以下内容:
Manipulate[x,

 myGrid[{
   {Control[{{x, 0, "x"}, 0, 10, 1}]},
   spec["Divider"],
   {Control[{{y, 0, "y"}, 0, 10, 1}]}
   }, Frame -> None
  ],

 Initialization :>
  {
   specfunc["Divider", lst_] := Dividers -> {None, # -> True & /@ lst};

   myGrid[dat_, opts : OptionsPattern[]] :=
    Module[{x = 1}, 
     Grid[#, opts, Sequence @@ #2] & @@ 
      Reap[If[MatchQ[#, _spec], Sow[x, #[[1]]]; ## &[], x++; #] & /@ 
        dat, _, specfunc]
     ]

   }
 ]

这会产生错误,因为 Mathematica 在读取和处理初始化部分之前尝试首先读取 Manipulate 的主体来解析它。

但是在 Manipulate 之外,它当然会起作用:
myGrid[{
  {Control[{{x, 0, "x"}, 0, 10, 1}]},
  spec["Divider"],
  {Control[{{y, 0, "y"}, 0, 10, 1}]}
  }, Frame -> None
 ]

specfunc["Divider", lst_] := Dividers -> {None, # -> True & /@ lst};
myGrid[dat_, opts : OptionsPattern[]] :=
 Module[{x = 1}, 
  Grid[#, opts, Sequence @@ #2] & @@ 
   Reap[If[MatchQ[#, _spec], Sow[x, #[[1]]]; ## &[], x++; #] & /@ 
     dat, _, specfunc]
  ]

enter image description here

我需要花更多的时间在这上面,看看我是否可以让它在 Manipulate 中工作。

顺便说一句,让这样的东西在 Manipulate 中工作真的很难。我知道的唯一技巧是在 With[{},.... Grid....] 中使用宏我从列昂尼德那里学到的模式。

例如,此类困难,请参阅我的这个问题

How to define constants for use with With[] in one place and then apply them later?

编辑(3)
我是我做错了什么,但我在 Manipulate 中遇到了一些错误:

第一个例子:
Manipulate[x,

 Evaluate@grid[{
    {Control[{{x, 0, "x"}, 0, 10, 1}]}
    }
   ],

 Initialization :> 
  {
   grid[tab_, opts___] := 
     Module[{divlocal, divglobal, div, pos}, 
      divglobal = (Dividers /. opts) /. Dividers -> {False, False};
      If[Depth[divglobal] == 1, divglobal = {divglobal, divglobal}];
      If[Length[divglobal] == 1, AppendTo[divglobal, False]];
      pos = Position[tab, Dividers -> _, 1];
      divlocal = 
       MapIndexed[# - #2[[1]] + 1 -> Dividers /. tab[[#]] &, 
        Flatten[pos]];
      divglobal[[2]] = {divglobal[[2]], divlocal};
      Grid[Delete[tab, pos], Dividers -> divglobal, opts]];


   }
 ]

给出错误:
ReplaceAll::rmix: Elements of {False,{}} are a mixture of lists and nonlists. >>

如果我将上面的替换为
Evaluate@grid[{
   Dividers -> {Thick, Blue},
   {Control[{{x, 0, "x"}, 0, 10, 1}]}
   }
  ],

试过 Dynamic@代替 Evaluate@没运气。可能是小修复是所有需要的吗?或者我没有正确使用它?

最佳答案

此解决方案应该允许您将表中指定的行之间的分隔符规范与使用 Dividers 指定的分隔符规范结合起来。选项。

grid[tab_, opts___] :=
 Module[{divlocal, divglobal, div, pos},

  (* extract option value of Dividers from opts to divglobal *)
  (* default value is {False, False} *)
  divglobal = (Dividers /. {opts}) /. Dividers -> {False, False};

  (* transform divglobal so that it is in the form {colspecs, rowspecs} *)
  If[Head[divglobal] =!= List, divglobal = {divglobal, divglobal}];
  If[Length[divglobal] == 1, AppendTo[divglobal, False]];

  (* Extract positions of dividers between rows from tab *)
  pos = Position[tab, Dividers -> _, 1];

  (* Build list of rules for divider specifications between rows *)
  divlocal = MapIndexed[# - #2[[1]] + 1 -> Dividers /. tab[[#]] &, Flatten[pos]];

  (* Final settings for dividers are {colspecs, {rowspecs, divlocal}} *)
  divglobal[[2]] = {divglobal[[2]], divlocal};
  Grid[Delete[tab, pos], Dividers -> divglobal, opts]]

要指定行之间的分隔符,您需要插入 Dividers->spec在所需位置spec要么是 False , True ,或图形指令(颜色、厚度等)。例如
tab = {{1, 2, 3}, Dividers -> {Thick, Blue}, {4, 5, 6}, {7, 8, 9}, 
   Dividers -> False, {10, 11, 12}};

grid[tab, Dividers -> All]

Mathematica graphics

编辑

应巫师先生的要求,我在我的代码中添加了一些注释。

关于wolfram-mathematica - 在需要时在行之间的网格内添加分隔线的任何技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8875970/

相关文章:

wolfram-mathematica - 如何停止在 Format/Interpretation Mathematica 结构中发生递归?

wolfram-mathematica - 如何简化/扩展/将模式应用于函数的参数

wolfram-mathematica - 如何控制 Manipulator 输入字段中的字体外观?

error-handling - Mathematica 中的可靠清理

wolfram-mathematica - 我怎样才能摆脱 Mathematica 中一个令人讨厌的前置因子?

wolfram-mathematica - 如何告诉 Mathematica 将 0 替换为 1 的幂?

wolfram-mathematica - for循环改变四维表的值

function - 创建自定义表格表示的函数

wolfram-mathematica - 在 Mathematica 中求解双调和方程

wolfram-mathematica - 生成目录