Mathematica Asked on February 9, 2021
I use Grid
to align controls in Manipulate. Here is a simple example
Grid[{
{name1,Control2,value1},
{name2,Control1,value2}
}]
The 3 fields above come out aligned automatically, even when one field, such as name, is longer than another, and Spacing
can be used to control field width for all controls at once.
A problem shows up when I need to use an If
statement to build controls based on selection used in previous control:
Grid[{
{name1,Control2,value1},
(*now make a control based on above value*)
{Dynamic[If[name1==1,
{name2,Control1,value2},
{name3,Control3,value3}
]
]
}
}]
This works well, and allows me to change the controls that appear on the UI based on a selection that was made in another control but the problem with the above is that it gives an extra set of {}
coming out from inside the If
needed grouping which ends up messing up the alignment.
I think I need to use Sequence
or some other function to remove the inner {}
but can’t figure the syntax.
I made below a simple working code to illustrate
Manipulate[
eq,
Grid[{
{"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},
{Dynamic[If[eq == 1,
{"v1",
Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],
Dynamic[v1]
},
{"v2",
Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}],
Dynamic[v2]
}
]], SpanFromLeft
}}
],
{{eq, 1}, None},
{{v1, 1}, None},
{{v2, 1}, None}
]
which gives
You can see that the whole expression was treated as if I wrote
Grid[{
{name1,Control2,value1},
{{name2,Control1,value2}}
}]
I tried using First
, Sequence
but can’t get it to come out correct.
Again, I need to keep the 3 fields in each Row
separate and in a List. I can’t just use Row
since it means each row will collapse to become one field, not three fields, and I lost the alignment I needed, i.e. I can’t just write
Manipulate[
eq,
Grid[{
{"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},
{
Dynamic[If[eq == 1,
Row[{"v1",
Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],
Dynamic[v1]
}],
Row[{"v2",
Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}],
Dynamic[v2]
}]
]], SpanFromLeft
}
}
],
{{eq, 1}, None},
{{v1, 1}, None},
{{v2, 1}, None}
]
Any idea how to make the above work and remove those extra {}
?
edit
Let me just clarify why using Row
as a solution does not work.
Compare the following 2 examples
Manipulate[eq,
Grid[{
{"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},
{Dynamic[If[eq == 1,
Row[{"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],Dynamic[v1]}],
Row[{"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}], Dynamic[v2]}]
]]
}
}],
{{eq, 1}, None},
{{v1, 1}, None},
{{v2, 1}, None}
]
We can see that the whole Row
was treated as one field. I want to the above to come out as if I have written this
Manipulate[eq,
Grid[{
{"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},
{"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],Dynamic[v1]}
}],
{{eq, 1}, None},
{{v1, 1}, None},
{{v2, 1}, None}
]
You see the difference? This is the important part. thanks.
Let's use a Column
of Row
s rather than a Grid
.
Manipulate[eq,
Column[{
Row[{"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},
StringJoin@@Table[" ",{52}]],
Dynamic[If[eq == 1,
Row[{"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],
Dynamic[v1]}, " "],
Row[{"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}],
Dynamic[v2]}, " "]
]
]
}],
{{eq, 1}, None},
{{v1, 1}, None},
{{v2, 1}, None}
]
I do think that the use of spaces to format is a bit hacky; I'm not certain how it will look across platforms. There might be a better way to do it - perhaps use of Pane
or Panel
or Spacings
or Margins
or I don't know what. I think the basic idea is there, though.
Answered by Mark McClure on February 9, 2021
Does this work as you need?
Manipulate[eq, Dynamic@Grid[{{"eq", SetterBar[Dynamic[eq], {1, 2}],
Dynamic[eq]}, {If[eq == 1,
{"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}], Dynamic[v1]},
{"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}],
Dynamic[v2]}], SpanFromLeft} /.
(lst : {x_String, _, _}) :> Sequence @@ lst}],
{{eq, 1}, None}, {{v1, 1}, None}, {{v2, 1}, None}]
Alternatively, instead of post-processing, you can define a custom if
that "holds" sequence arguments as follows:
ifSeqHold = Function[{test, arg1, arg2},
If[test, Sequence @@ arg1, Sequence @@ arg2], HoldAllComplete];
Manipulate[eq, Dynamic@Grid[{{"eq", SetterBar[Dynamic[eq], {1, 2}],
Dynamic[eq]}, {ifSeqHold[ eq == 1,
{"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}], Dynamic[v1]},
{"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}],
Dynamic[v2]}], SpanFromLeft}}],
{{eq, 1}, None}, {{v1, 1}, None}, {{v2, 1}, None}]
which gives the same result.
Update: Hold[Sequence@@{...}]
followed by ReleaseHold
also works:
Manipulate[eq, Dynamic@Grid[{{"eq", SetterBar[Dynamic[eq], {1, 2}],
Dynamic[eq]}, {If[eq == 1,
Hold[Sequence @@ {"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],
Dynamic[v1]}],
Hold[Sequence @@ {"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}],
Dynamic[v2]}]]// ReleaseHold, SpanFromLeft} }],
{{eq, 1}, None}, {{v1, 1}, None}, {{v2, 1}, None}]
Answered by kglr on February 9, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP