0
$\begingroup$

It appears that I can set the range to a Dynamic variable in a Manipulate control, but not in a SetterBar control? :

Manipulate[
 tick;
 Dynamic@If[ tabNumber == dynTab, Plot[ x^2, {x, 0, 1}],
   Plot[ 1 - x^2, {x, 0, 1}]]
 , TabView[ {
   "dynamic range" -> Column[ tabNumber = dynTab ; {
      Row[{Manipulator[
         Dynamic[m2, (m2 = #; tick = Not[tick]) &], {2, Dynamic@range,
           2}], " ", Dynamic[m2] }],
      Row[{SetterBar[Dynamic[s2, (s2 = #; tick = Not[tick]) &],
         Range[Dynamic@range]], " ", Dynamic[s1] }]
      }],
   "static range" -> Column[ tabNumber = staticTab ; {
      Row[{Manipulator[
         Dynamic[m1, (m1 = #; tick = Not[tick]) &], {2, 8, 2}], " ",
        Dynamic[m1] }],
      Row[{SetterBar[Dynamic[s1, (s1 = #; tick = Not[tick]) &],
         Range[8]], " ", Dynamic[s1] }]
      }]
   }, Dynamic @tabNumber ]
 , {{tick, False}, None}
 , {{tabNumber, 1}, None}, {{dynTab, 1}, None}, {{staticTab, 2}, None}
 , {{m1, 2}, None}, {{m2, 2}, None}, {{s1, 2}, None}, {{s2, 2}, None}
 , {{range, 8}, None}
 , TrackedSymbols :> {tick}, ControlPlacement -> Left
 ]

This produces an error 'Range::range: "Range specification in Range[range] does not have appropriate bounds. "':

Range error

Observe that the Manipulate in the same tab that uses a Dynamic range works fine. The other tab (not shown in the image) that uses static ranges is fine (for both Manipulate and SetterBar)?

[EDIT:]

Nasser suggested Evaluate@With[{range = ...}, ...], which assumed range was constant, as in the example above. Here's an example that is more representitive of what I'm attempting to do (with range based on the count of the number of Locators in a LocatorPane, which can be added with Alt-Click in that pane).

Manipulate[tick;
 If[tabNumber == dynTab, Plot[x^2, {x, 0, 1}],
  Plot[1 - x^2, {x, 0, 1}]]
 , TabView[{
   "use n-loc as range" -> Column[tabNumber = dynTab; {
      "dynamic range manipulators:",
      Row[{Manipulator[Dynamic[m2, (m2 = #; tick = Not[tick]) &],
         Dynamic@{1, 2 range}], " ", Dynamic[m2]}],
      Row[{SetterBar[Dynamic[s2, (s2 = #; tick = Not[tick]) &],
         Dynamic@Range[range]], " ", Dynamic[s1]}],
      "static range manipulators:",
      Row[{Manipulator[
         Dynamic[m1, (m1 = #; tick = Not[tick]) &], {1, 4}], " ",
        Dynamic[m1]}],
      Row[{SetterBar[Dynamic[s1, (s1 = #; tick = Not[tick]) &],
         Range[4]], " ", Dynamic[s1]}]
      }],
   "loc" -> Column[tabNumber = staticTab; {
      LocatorPane[ Dynamic[u, (
          u = # ;
          range = (Dimensions[u] // First);
          tick = Not[tick]) &],
       Plot[x^3, {x, -1, 1}, PlotRange -> {{-1, 1}, {-1, 1}}],
       LocatorAutoCreate -> True,
       ContinuousAction -> False
       ]
      , Row[{"u = ", Dynamic@u}]
      }]
   }, Dynamic@tabNumber]
 , {{tick, False}, None}
 , {{u, {{0.5, 0.3}, {0.3, 0.9}}}, None}
 , {{tabNumber, 1}, None} , {{dynTab, 1}, None} , {{staticTab, 2}, None}
 , {{m1, 2}, None} , {{m2, 2}, None} , {{s1, 2}, None} , {{s2, 2}, None}
 , {{range, 2}, None}
 , TrackedSymbols :> {tick}, ControlPlacement -> Left
 (*use a global (comment out range above to try) ... doesn't work: *)
 (*, Initialization\[RuleDelayed] { range = 2 ; }*)
 ]

In this example, I put the Dynamic outside of the Range expression. This eliminates the error text, but still doesn't work. The SetterBar shows up as text: SetterBar[2, {1,2}]

$\endgroup$
2
  • $\begingroup$ 1. As you have discovered you cannot have Head of Dynamic within Range. 2. It isn't clear from your code why you need to be using Dynamic in any case because you only have one static value for range. Since it doesn't change it doesn't need updating. 3. If you modify your code to allow multiple values of range then try Dynamic[SetterBar[Dynamic[s2, (s2 = #; tick = Not[tick]) &], Range[range]], TrackedSymbols :> {range}] $\endgroup$ Feb 5, 2014 at 22:00
  • $\begingroup$ I'd added the second example to illustrate why I wanted a Dynamic Range. Your comment is really an answer, since Dynamic@SetterBar does the trick. $\endgroup$ Feb 6, 2014 at 1:35

2 Answers 2

1
$\begingroup$
Dynamic[SetterBar[Dynamic[s2, (s2 = #; tick = Not[tick]) &], Range[range]], 
TrackedSymbols :> {range}]
$\endgroup$
3
$\begingroup$

This has to do with evaluation for controls settings and the order Manipulate reads the controls and when things gets evaluated initially. That is why you'll see all settings for controls use hardcoded numerical values right there, since these have their values known at the instance they are read. I've always had hard time with this part.

But to make a long story short, since your range value is constant, and not used anywhere, other than just for the control setting, a simple workaround, and I think the correct way to do this anyway, is to use With, like this:

Manipulate[
 tick;

 If[tabNumber == dynTab,
  Plot[x^2, {x, 0, 1}], Plot[1 - x^2, {x, 0, 1}]
  ],

 Evaluate@With[{range = 8},
   TabView[
    {
     "dynamic range" -> Column[tabNumber = dynTab;
       {Row[{Manipulator[Dynamic[m2, (m2 = #; tick = Not[tick]) &], 
       {2, range, 2}], " ", Dynamic[m2]}], 
        Row[{SetterBar[Dynamic[s2, (s2 = #; tick = Not[tick]) &], Range[range]], 
        " ", Dynamic[s2]}]}
       ],

     "static range" -> Column[tabNumber = staticTab;
       {Row[{Manipulator[Dynamic[m1, (m1 = #; tick = Not[tick]) &], {2, 8, 2}],
        " ", Dynamic[m1]}], 
        Row[{SetterBar[Dynamic[s1, (s1 = #; tick = Not[tick]) &], Range[range]], 
        " ", Dynamic[s1]}]}
       ]
     },
    Dynamic@tabNumber
    ]
   ],

 {{tick, False}, None},
 {{tabNumber, 1}, None},
 {{dynTab, 1}, None},
 {{staticTab, 2}, None},
 {{m1, 2}, None},
 {{m2, 2}, None},
 {{s1, 2}, None},
 {{s2, 2}, None},
 ControlPlacement -> Left,
 TrackedSymbols :> {tick}
 ]

Mathematica graphics

See if the above works for you.

btw, you do not need to add Dynamic to the If statement above. So I removed it. Also, for your TabeView, you can use Grid to layout the controls below each tab, much easier than used Column and Rows, but these are side issues. Here is a version using Grid

Manipulate[
 tick;

 If[tabNumber == dynTab,
  Plot[x^2, {x, 0, 1}], Plot[1 - x^2, {x, 0, 1}]
  ],

 Evaluate@With[{range = 8},
   TabView[
    {
     "dynamic range" ->
      Grid[{
        {Manipulator[Dynamic[m2, (m2 = #; tabNumber = dynTab; tick = Not[tick]) &], 
        {2, range, 2}], Dynamic[m2]},
        {SetterBar[Dynamic[s2, (s2 = #; tick = Not[tick]) &], Range[range]], 
        Dynamic[s2], SpanFromLeft}
        }, Alignment -> Left],

     "static range" ->
      Grid[{{
         Manipulator[Dynamic[m1, (m1 = #; tabNumber = staticTab; tick = Not[tick]) &],
         {2, 8, 2}], Dynamic[m1]}, 
         {SetterBar[Dynamic[s1, (s1 = #; tick = Not[tick]) &], Range[range]], 
         Dynamic[s1], SpanFromLeft}
        }, Alignment -> Left]
     },
    Dynamic@tabNumber
    ]
   ],

 {{tick, False}, None},
 {{tabNumber, 1}, None},
 {{dynTab, 1}, None},
 {{staticTab, 2}, None},
 {{m1, 2}, None},
 {{m2, 2}, None},
 {{s1, 2}, None},
 {{s2, 2}, None},
 ControlPlacement -> Left,
 TrackedSymbols :> {tick}
 ]
$\endgroup$
4
  • $\begingroup$ I actually want range to be non-constant, set as a side effect of an Alt-click in a LocatorPane (trying the Evaluate@With[{range = 2 n},...], where n is a different Manipulate variable produces the same error. The answer mathematica.stackexchange.com/questions/13658/… seems to suggest that this is an acknoledged Mathematica bug (where the suggested work around is to use a global variable). $\endgroup$ Feb 5, 2014 at 14:29
  • $\begingroup$ @PeeterJoot You say I actually want range to be non-constant. Ok, but in the code you posted, range was not used anywhere else other than in setting the controls. So that is why I assumed it constant. Ofcourse using range as global will always work, but if you making a demo, you can't have a global cell in the demonstration notebook and everything has to be inside the Manipulate. Even in the Initialization section, it will not work due to order of evaluation. May be it is a bug then for this control. If your setting allows using global variables, then may be this a solution you can use. $\endgroup$
    – Nasser
    Feb 5, 2014 at 14:41
  • $\begingroup$ I've posted a more representative sample. $\endgroup$ Feb 5, 2014 at 15:17
  • $\begingroup$ fyi. The Dynamic@If is required if you want the plot to update on click of the Tab. Without that it doesn't update until you click on one of the controls within that tab. $\endgroup$ Feb 6, 2014 at 13:23

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.