Укажите локальную динамику в сетке - PullRequest
7 голосов
/ 10 января 2012

Я бы хотел динамически обновлять определенные части 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 используется в любом изa, b или c, и я НЕ хочу обновлять их при изменении show, их изменения зависят от других триггеров.Почему бы тогда не удалить show из символов первого ряда?Представьте себе, я не могу, поскольку show присутствует в функции, которая используется в a, b или c, и к этой функции я не могу получить легкий доступ.

Конечно, переносПервый аргумент 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]

Хотелось бы узнать, есть лиРешение этой конкретной проблемы путем локального применения оболочки Dynamic к строке.

Ответы [ 2 ]

3 голосов
/ 11 января 2012

Вот решение с использованием экспериментального 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, что вы и хотели:

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

enter image description here

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

пс.Мне нужно больше работать над правильным размещением строки сетки ....

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

enter image description here

1 голос
/ 11 января 2012

Это на самом деле комментарий к решению @ Nasser и предложенное исправление, чтобы избежать ручного разбиения второго ряда, но из-за нехватки места в области комментариев я публикую его как ответ.Будем рады удалить его, как только Насер подтвердит, что он работает и включит его в свой ответ.

Ключ к решению можно найти в разделе Possible Issues в Item документации:

Если Item не является самым верхним элементом дочернего элемента функции, поддерживающей Item, он не будет работать.

Я использую это для изменения решения @ Nasser вследующим образом.Во-первых, мне нужно изменить определение 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 Обертка на самом деле не нужна;это работает так же хорошо без него:

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