2
$\begingroup$

Given a certain Control object (checkbox, for example) within a Manipulate environment, my goal is to define another control which is inactivated if the first control is active (or satisfies some condition). How do I do this efficiently? Are there built in functions to help me do this?

A first idea was to simply create an If condition within a Dynamic@Grid in the Control panel, as follows

Manipulate[b,
 Dynamic@Grid[{
    {"a", Control[{{a, 0, ""}, {1, 0}}]},
    If[a == 0,
     {"b", Control[{{b, 0, ""}, {1, 0}}]},
     b = 0;
     {Style["b", Gray], Control[{{b0, 0, ""}, {1, 0}}]}
     ]},
 Alignment -> {{Right, Left}, Automatic}], 
 ControlPlacement -> Left]

which gives

enter image description here

enter image description here

Here I'm creating a null control b0 to replace b and setting b = 0 for convenience.

This not bad, but I would like to check if any of the following are possible:

  1. Add a Gray tone to checkbox b whenever it's inactive;
  2. Make it impossible to interact with checkbox b if inactive, that is, lock the dependent control in a specific state;
  3. Find an efficient way to do this for multiple controls and dependencies, and avoid creating null controls as mentioned (for example, maybe I could simply define a function that toggles st in Style["b",st], for st = Black or st = Gray, and force b = False when a = 1).

Any ideas?

$\endgroup$
4
$\begingroup$

Use Dynamic[a == 0] as the option setting for Enabled in the second control:

Manipulate[b, 
 {{a, 0, "a"}, {1, 0}},
 {{b, 0, "b"}, {1, 0}, Enabled -> Dynamic[a == 0]}, 
 ControlPlacement -> Left]

enter image description here

If you need to fade the label when the control is not enabled:

Manipulate[b, 
  {{a, 0, "a"}, {1, 0}}, 
  {{b, 0, Dynamic[If[a == 0, "b", Style["b", GrayLevel[.7]]]]}, {1, 0}, 
     Enabled -> Dynamic[a == 0]}, 
  ControlPlacement -> Left]

enter image description here

If the second control is a slider, that is, if you use

 {b, 0, Dynamic[If[a == 0, "b", Style["b", GrayLevel[.7]]]]}, 0, 1, 
    Enabled -> Dynamic[a == 0]}

for the second control, you get

enter image description here

Update: An alternative approach is to use the option TrackingFunction in the first control to update all dynamic variables that depend on a:

Manipulate[b, 
 {{a, 0, "a"}, {1, 0}, TrackingFunction -> 
    (a = #; b = (1 - a) b; benabled = a == 0; 
     sty = (a /. {0 -> Black, 1 -> GrayLevel[.8]}); &)}, 
 {{b, 0, Dynamic@Style["b", sty]}, {1, 0}, Enabled -> Dynamic[benabled]}, 
 {{benabled, True}, None}, 
 {{sty, Black}, None}, 
 ControlPlacement -> Left]

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ Can I set b = 0 when a = 1 in your first solution? $\endgroup$ – sam wolfe Feb 20 at 15:20
  • $\begingroup$ @sam, maybe replace b in the first argument of Manipulate with Dynamic[b = (1 - a) b]? $\endgroup$ – kglr Feb 20 at 15:36
  • 1
    $\begingroup$ I can incorporate it in the If you have on your second code, and that's actually even better. Didn't know about the Enabled option. This is great, thanks! $\endgroup$ – sam wolfe Feb 20 at 15:38
  • 1
    $\begingroup$ It's even better if I define If[a == 1, b = 0; sty = Gray, sty = Black]; right after Dynamic@Grid[{, and simply have Style["b",sty] in the control. This helps me to change a lot of widget dependencies easier. $\endgroup$ – sam wolfe Feb 20 at 15:53

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.