5
$\begingroup$

Is it possible to stylize Manipulate so that there is a line separating the control and the content? The code

Manipulate[Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}],
 {x, 10, 100, 1},
 {y, 10, 100, 1},
 ControlPlacement -> Left]

gives

enter image description here

but I'm looking for something like

enter image description here

Playing around with Framed and the option Paneled I can do something like

Framed[Manipulate[Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}],
  {x, 10, 100, 1},
  {y, 10, 100, 1},
  ControlPlacement -> Left, Paneled -> False], FrameMargins -> 10]

which gives

enter image description here

Now I would just need to include a line. Just an idea. Any thoughts?

$\endgroup$

3 Answers 3

6
$\begingroup$

The most general solution is to do the whole layout yourself.

You can actually use Control and put the controls themselves in the Grid along with your output.

So you will have only ONE grid, which now includes everything in it. Both the controls and the final output of your Manipulate code. This gives you full control of what you want to do. For your example, you can then do

Manipulate[ 
 Grid[{
   {Grid[{
      {"x", Control[{x, 10, 100, 1}]},
      {"y", Control[{y, 10, 100, 1}]}
      }]
    ,
    Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}]
    }
   }, Frame -> All, FrameStyle -> Gray]
 ,
 Paneled -> False]

enter image description here

And if you want just a line between the controls and the plot then

Manipulate[ 
 Grid[{
   {Grid[{
      {"x", Control[{x, 10, 100, 1}]},
      {"y", Control[{y, 10, 100, 1}]}
      }]
    ,
    Item[Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}], 
     Frame -> {{True, False}, {False, False}}]}
   }]
 ,
 Paneled -> False]

enter image description here

But now since you have everything inside a Grid, you can play with the layout as you want. For example, you can do this

Manipulate[ 
 Grid[{
   {Grid[{
      {"x", Control[{x, 10, 100, 1}]},
      {"y", Control[{y, 10, 100, 1}]}
      }]
    },
   {
    Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}]
    }
   }, Frame -> All, FrameStyle -> {Dashed, Red}, Spacings -> {1, 1}]
 ,
 Paneled -> False]

enter image description here

Or you can put one control above, and one below

Manipulate[ 
 Grid[{
   {"x", Control[{x, 10, 100, 1}]},
   {Item[Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}], Frame -> All], 
    SpanFromLeft},
   {"y", Control[{y, 10, 100, 1}]}
   }, Frame -> True, FrameStyle -> Gray, Spacings -> {1, 1}
  ]
 ,
 Paneled -> False]

enter image description here

And so on. The choices are limitless.

You can change the style of the Frame and change the size of the controls as well. Basically you can now use all the styling available for Grid and Frame as you want and not worry about Manipulate itself.

$\endgroup$
4
  • $\begingroup$ Shouldn't you be able to simply leave the Manipulate away, since at this point, it's neither doing control construction nor localization of variables? $\endgroup$
    – Lukas Lang
    Jul 2, 2021 at 22:10
  • $\begingroup$ @LukasLang sorry, I do not understand what you mean by leave the Manipulate away. $\endgroup$
    – Nasser
    Jul 2, 2021 at 23:11
  • $\begingroup$ I was originally thinking that you could just keep the Grid[...] part without the Manipulate wrapper. You only have to add Dynamic around the plot (which would otherwise be done by Manipulate, and it would work the same. But I think it's better to actually tell Manipulate what the variables of your controls are, see my answer for the details $\endgroup$
    – Lukas Lang
    Jul 3, 2021 at 13:10
  • $\begingroup$ Great answer! I suppose that with this approach it is not possible to keep the "more options circular extender" that usually appears within the Manipulate content (top right corner) still only on the right panel, correct? $\endgroup$
    – sam wolfe
    Jul 5, 2021 at 12:06
2
$\begingroup$

Note: This solution is heavily based on the one by @Nasser, this is just to show how to make better use of Manipulate.

Here's how I would do it:

Manipulate[
 Grid[
  {{
    Grid[
     {{"x", Control[{x, 10, 100, 1}]},
      {"y", Control[{y, 10, 100, 1}]}}
     ],
    Item[
     Dynamic@Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}],
     Frame -> {{True, False}, {False, False}}
     ]}}
  ],
 {{x, 10}, None}, {{y, 20}, None},
 Paneled -> False
 ]

enter image description here

The differences to the answer from @Nasser are:

  • Dynamic wrapped around the plot. This makes sure the sliders work as expected, because otherwise dragging the slider will redraw the slider itself.
  • {{x, 10}, None} as argument to Manipulate. This tells Manipulate that x should be one of the variables to localize, but that it shouldn't create a control. The 10 is the initial value for x, so you can easily set that as well. This should make the whole thing work better when restarting Mathematica.
$\endgroup$
2
$\begingroup$

We can also use the (undocumented) Method option "ControlAreaDisplayFunction" with a custom function that gives the desired look:

ClearAll[controlAreaDisplayFunction]
controlAreaDisplayFunction[side_: Right, itemsize_: Automatic, alignment_: Automatic, 
  spacings_: Automatic, style_: GrayLevel[0, .2]] := Grid[{{
    Item[#, ItemSize -> itemsize /. Automatic -> 
     (side /. {Right | Left -> {All, Scaled[1/3]}, Top | Bottom -> {Scaled[1/3], All}}),
    Frame -> MapAt[style &, {{None, None}, {None, None}}, 
      side /. {Top -> {2, 2}, Bottom -> {2, 1}, Left -> {1, 1}, Right -> {1, 2}}]]}},
   Alignment -> alignment /. Automatic -> 
     (side /. {Right -> {Left, Center}, Left -> {Right, Center},
          Top -> {Center, Top}, Bottom -> {Center, Bottom}}), 
   Spacings -> spacings /. Automatic -> 
     (side /. { Left | Right -> {5, 0}, Top | Bottom -> {0, 5}})] &

Examples:

Panel @ Manipulate[Plot3D[Sin[x + u + v + y^2], {u, -3, 3}, {v, -2, 2}, 
    ImageSize -> 300],
  {x, 10, 100, 1}, {y, 10, 100, 1}, 
  ControlPlacement -> Left, 
  Paneled -> False, 
  Method -> {"ControlAreaDisplayFunction" -> controlAreaDisplayFunction[]}]

enter image description here

Use ControlPlacement -> Right and "ControlAreaDisplayFunction" -> controlAreaDisplayFunction[Left] to get

enter image description here

Use ControlPlacement -> Bottom and "ControlAreaDisplayFunction" -> controlAreaDisplayFunction[Top] to get

enter image description here

Use ControlPlacement -> Top and "ControlAreaDisplayFunction" -> controlAreaDisplayFunction[Bottom] to get

enter image description here

Replace controlAreaDisplayFunction[Bottom with controlAreaDisplayFunction[Bottom, Automatic, Automatic, Automatic, Directive[AbsoluteThickness[5], Orange]] to get

enter image description here

$\endgroup$
4
  • $\begingroup$ Thanks for the answer. Would it be somehow possible to actually make the vertical delimiter connect to the top and bottom horizontal delimiters just to avoid that tight spacing (first example)? $\endgroup$
    – sam wolfe
    Jul 4, 2021 at 10:51
  • $\begingroup$ @samwolfe, unfortunately I don't know how to make the delimiters to connect to the outer frame. $\endgroup$
    – kglr
    Jul 4, 2021 at 14:01
  • $\begingroup$ For some reason your solution is resulting and very long cell. Any idea why? I'm using Mathematica 12.2. $\endgroup$
    – sam wolfe
    Jul 7, 2021 at 14:37
  • $\begingroup$ @samwolfe, I am using version 11.3. I tried the same code on version 12.3 (Wolfram Cloud) ; somehow, the control area is not centered. $\endgroup$
    – kglr
    Jul 8, 2021 at 4:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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