2
$\begingroup$

I'm trying to dynamically change the number of Popup menus and Grid cells in Manipulate and connect the chosen values to the displayed Grid.

I have gotten as far as this:

Manipulate[Grid[Table[v, {x, h}, {y, w}], Frame -> All],
 {{h, 2}, 1, 5, 1}, {{w, 2}, 1, 5, 1}, 
 Dynamic@Panel[
   Grid[Outer[PopupMenu[Dynamic[v], {1, 2, 3, 4}] &, Range[h], 
     Range[w]]]]] 

enter image description here

I can change the number of popup menus and the Grid cells change as well. However, each popup menu should correspond to a Grid cell and selection a value should update the value in the Grid cell, e.g. top left popup menu should update the value in the top left Grid cell.

But the problem is, that every popup menu needs its own Dynamic variable. With my approach, the value is updated in the entire Grid and the popup menus behave as one.

I hope it became clear. Any ideas how to change the code to make this work?

$\endgroup$
  • 1
    $\begingroup$ Related: 77049 $\endgroup$ – Edmund Aug 20 '17 at 12:41
  • $\begingroup$ If you reduce the rows or columns what are you expecting to happen to the values in those rows and columns? $\endgroup$ – Edmund Aug 20 '17 at 13:29
  • $\begingroup$ @Edmund: Not sure I understand what you mean. There will be at least one Grid cell and one popup menu. The other values (rows, columns) will not be displayed then. $\endgroup$ – holistic Aug 20 '17 at 13:42
  • $\begingroup$ If you are displaying a 2x2 grid and you reduce the number of rows then you no longer see the second row. That row had values in it. When you increase the number of rows to 2 rows do you expect the values that were there previously in the second row to still be available or do you expect the second row to fill with default values? $\endgroup$ – Edmund Aug 20 '17 at 13:47
  • $\begingroup$ Ah I see. It should be the default values again. $\endgroup$ – holistic Aug 20 '17 at 14:29
2
$\begingroup$

Each PopupMenu will need its own Dynamic store of the value. This does not have to be a variable but instead can be a location in an array. Using the index scoping presented in this answer (77049) the requested Grid can be created.

Since the OP would like the values that are hidden during redimensioning to be remembered the complete array with default values is created first. There is a solution that allows for the array to start with the default dimensions and then be grown/shrunk dynamically but that is not required here and would result in the values of the rows and columns that go out of range of the dimensions to lost.

vals = Partition[Range@25, 5];

Then Manipulate is called.

Manipulate[
 Dynamic[
  Grid[
   Table[
    With[{r = \[FormalR], c = \[FormalC]},
     PopupMenu[Dynamic[vals[[r, c]]], Range@25]
     ],
    {\[FormalR], rows}, {\[FormalC], cols}]],
  TrackedSymbols :> {rows, cols}
  ]
 ,
 {{rows, 2}, 1, 5, 1},
 {{cols, 2}, 1, 5, 1}
 ]

Mathematica graphics

Each PopupMenu is linked to a position in the vals array. As the popups are updated so are the values in the array. This can be seen by evaluating Dynamic[Grid@vals] in a new cell and noticing that its values update with the Manipulate.

As the PopupMenu Grid is redimensioned the values outside of the row and column range remain so that when they come back into range their value is displayed.

Hope this helps.

$\endgroup$
  • $\begingroup$ Thank you, Edmund! Nice solution, but there needs to be also a Grid displaying the values of the popup menus below. This is shown in my code. Is it possible to add this somehow? $\endgroup$ – holistic Aug 20 '17 at 16:22
  • 1
    $\begingroup$ @holistic You can add in a Dynamic[Grid[vals[[ ;; rows, ;; cols]]]] and place that and the existing Grid in Column. $\endgroup$ – Edmund Aug 20 '17 at 17:19
  • $\begingroup$ Works great, thanks for the help! $\endgroup$ – holistic Aug 20 '17 at 17:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.