любой трюк, чтобы добавить разделитель внутри сетки между рядами в точке, где это необходимо - PullRequest
5 голосов
/ 16 января 2012

Чтобы добавить делитель между строками в сетке, я знаю, как это сделать, используя опцию Dividers.Но это используется в конце, и тогда нужно знать номер строки, под которой должен находиться делитель.Поэтому для большой сетки я использую метод проб и ошибок, пока не найду правильный номер строки.Затем, когда я изменю сетку позже, мне придется снова сделать пробу и ошибку, чтобы поместить делитель в правильное место, если он переместился после моих изменений.

В этом примере есть сетка с 3 рядамии я хочу добавить разделитель ниже, скажем, во второй строке, чтобы я мог сделать это:

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

Другой способ, это поставить False и True, в правильном порядке, где я хочу разделитель,как это

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

enter image description here

Было бы неплохо, если бы я мог сделать что-то подобное (как можно сделать для Манипуляции) (конечно, это ниже не работает здесь)

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

или

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

или что-то подобное.

Это облегчит обслуживание кода.

Я рассмотрел использование Item и тому подобное для этого,но не в состоянии понять это.

Кто-нибудь знает хитрость, чтобы сделать это?

edit:

Кстати, этот трюк, если это возможно, относится не только к разделителям.Но было бы полезно иметь возможность использовать многие другие параметры сетки, которые теперь выполняются на уровне сетки, а также на уровне элементов.Например, если я хочу добавить дополнительный пробел после некоторой строки, это будет легче сказать прямо в том темпе, в котором я хотел это сделать.Кроме того, если я хочу изменить размер элемента, проще сделать это на месте, то же самое для интервалов и т. Д., Чтобы при перемещении / копировании кода для всей строки или элемента он сам содержался и копировал его со всеми егоопции вместе.

Думаю, теперь для этого может потребоваться добавить новую опцию в Mathematica Grid, чтобы она работала правильно и была совместима со всей сеткой.

Это все, пока не будет создан GUI-конструктор для Mathematica.

Я обнаружил, что трачу больше 60% своего времени, когда пишу демонстрационную версию, чтобы графический интерфейс соответствовал и выглядел правильно.Со сборщиком GUI я могу вместо этого потратить время на работу над алгоритмом.Когда я использую Matlab GUIDE для создания GUI, мне требуется менее 5% моего времени на создание аналогичного GUI.

Я хотел бы, чтобы WRI сделал конструктор GUI для Mathematica, я думаю, что это будет убийственное приложение для Mathematica, если вы спросите меня.Но никто не спросил меня:)

edit (2)

Комментарий к хорошему решению Mr Wizard ниже.
В основном я хотел использовать эту функцию для используемых мной сетокрасположить элементы управления для 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 для настройки элементов управления).Я не могу использовать вызовы функций здесь.Я не могу написать, используя приведенное ниже решение Wizard, следующее:

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, чтобы проанализировать его, ДО чтения и обработки раздела инициализации.

Но вне Манипуляции, это, конечно, будет работать:

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

Мне нужно потратить больше времени на это, чтобы посмотреть, смогу ли я получить егоработать внутри Манипуляций.

кстати, заставить подобные вещи работать в Манипуляциях действительно сложно.Единственный известный мне трюк - использование макросов с шаблоном With[{},.... Grid....], который я узнал от Леонида.

Например, о таких трудностях, см. Мой вопрос

Как определить константы для использования с With [] в одном месте, а затем применить их позже?

edit (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@ Не повезло.может быть небольшая починка это все что нужно?или я не правильно его использую?

Ответы [ 2 ]

4 голосов
/ 16 января 2012

Это решение должно позволить вам комбинировать спецификации для разделителей между строками, указанными в таблице, с теми, которые указаны с помощью опции 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

Редактировать

Я добавил несколько комментариев к своему коду по просьбе мистера Волшебника.

2 голосов
/ 16 января 2012

Я предлагаю вам использовать новую головку, которая может содержать инструкции (spec ниже), и новую функцию, которая обрабатывает эти инструкции (specfunc ниже) в соответствии с индивидуальными требованиями.Преимущество состоит в том, что это легко обобщается для различных чередующихся инструкций, и каждая из них может обрабатываться произвольным образом.

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

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

Использование:

dat =
{
   {1, 2, 3},
   {4, 5, 6},
   spec["Divider"],
   {7, 8, 9}, 
   spec["Divider"],
   {"a", "b", "c"}
};

myGrid[dat, Frame -> True]

Mathematica graphics


Если каждая инструкция может быть одной строкой, такой как "Divider", и у вас нет конфликта при использовании их таким образом, вы можете исключить spec и использовать MatchQ[#, _String] и Sow[x, #].


Обращаясь к вашему обновленному вопросу, как я отметил в комментарии ниже, я считаю, что имеет больше смысла использовать самые базовые элементы в вашем конечном Manipulate объекте и писать инструменты, которые помогут вам создать этот объект наиболее легко.Я полагаю, что попытка выполнить такую ​​настройку внутри самого блока Manipulate обречена на неудачу, и, вероятно, странным и непрозрачным способом.

Тем не менее, для этого конкретного случая это работает, хотя я сомневаюсьэто надежно:

Manipulate[x,
 Evaluate[
  {specfunc["Divider", lst_] := Dividers -> {All, # -> True & /@ lst};
   myGrid[dat_, opts : OptionsPattern[]] := 
    Module[{x = 1}, 
     Grid[#, opts, Sequence @@ #2] & @@ 
      Reap[If[MatchQ[#, _spec], Sow[x, #[[1]]]; ## &[], x++; #] & /@ 
        dat, _, specfunc]]};
  myGrid[{{Control[{{x, 0, "x"}, 0, 10, 1}]}, 
    spec["Divider"], {Control[{{y, 0, "y"}, 0, 10, 1}]}}, 
   Frame -> True]
  ]
 ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...