7
$\begingroup$

I'm trying to build an ExampleData browser, so that the "collection"/"type" is selectable in a drop down menu, and the "name" is selectable in another drop down menu. What I have so far:

DynamicModule[ {},
 Panel[
  Column[{
    PopupMenu[Dynamic[q], ExampleData[]],
    (PopupMenu[Dynamic[h], Last[##] & /@ ExampleData[#]]) & /@ 
     Dynamic[q],
    ExampleData[Dynamic[q], Dynamic[h]]
    }]
  ]
 ]

...Only produces a nice error message: ExampleData is not evaluating!

Why isn't ExampleData evaluating the dynamic value of q & h? (i.e. ExampleData["TestImage", "Aerial2"])

$\endgroup$
3
  • 1
    $\begingroup$ Dynamic@ExampleData[{q, h}] (instead of ExampleData[Dynamic[q], Dynamic[h]]) works (but ... slow ) $\endgroup$
    – kglr
    Jul 11, 2014 at 20:05
  • $\begingroup$ Suggest as an answer? (with an explanation as to why this fixes the problem?) $\endgroup$ Jul 12, 2014 at 0:36
  • 1
    $\begingroup$ suggestion in my comment fixes one of the problems. As to why it does (1) ExampleData[a,b] should be ExampleData[{a, b}], (2) the error message "Dynamic[q] is not a known collection for ExampleData" gives a hint: Dynamic[q] and q are quite different objects. The more important issue is updating h properly when q is changed so that the {q,h} combination is a valid input for ExampleData so that ExampleData is not called with an input like {"AerialImage", "CatFur"}:). Maybe someone else can come up with a complete solution while I explore some approaches. $\endgroup$
    – kglr
    Jul 12, 2014 at 1:18

1 Answer 1

10
$\begingroup$

Dynamic is sometimes too aggressive for some purposes. You need to make sure Dynamic updates only when you are ready for new results. Besides, to ensure that Dynamic will have enough time to process your request it is sometimes a good idea to use SynchronousUpdating option. In the solotuion below you will see that instead of calculating the menu options inside the Popup Dynamic, these are calculated in the external Dynamic where the SynchronousUpdating option will avoid aborted calculations.

DynamicModule[{readyQ = False, menu2Options = {}, q = "", h = "", 
  optCnt = 0, pSize = {400, 100}},
 Panel@
  Column[{
    PopupMenu[Dynamic[q, 
      (q = #;
        readyQ = False;
        optCnt++;
        ) &]
     , ExampleData[]
     , Style["Select One", Red]
     ]
    ,
    Dynamic[
     Refresh[
      menu2Options = If[q === "", {}, Last[##] & /@ ExampleData[q]];
      Column[{
        If[ListQ@menu2Options,
         PopupMenu[Dynamic[h,
           (h = #;
             readyQ = True;
             optCnt++;
             ) &
           ]
          , menu2Options
          , Style["Select One", Red]
          ]
         ,
         "No options found."
         ]
        ,
        Pane[
         If[readyQ, ExampleData[{q, h}], "Waiting for your selection."]
         , ImageSize -> Dynamic[pSize]
         , Scrollbars -> Automatic
         ]
        }]
      , TrackedSymbols -> {optCnt}]
     , SynchronousUpdating -> Automatic
     ]
    }
   ]
 ]
$\endgroup$
3
  • $\begingroup$ Awesome. Not MAXIMALLY elegant, but awesome. $\endgroup$ Jul 23, 2014 at 2:46
  • $\begingroup$ To make my solution more elegant I could have used ActionMenu instead of PopupMenu but that would add some more code and the solution would be a little bit less easy to understand. I think that the community may benefit from a discussion about what you think makes my solution less elegant than possible or expected. Is it that I could have created a more elegant solution or that Mathematica is not allowing me to do so? $\endgroup$ Jul 25, 2014 at 17:19
  • $\begingroup$ This is good -- should be a resource function. $\endgroup$ May 23, 2021 at 19:05

Your Answer

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

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