3
$\begingroup$

I'm using Manipulate together with CreateDialog to run a ListPlot whenever I click on a simulation button. That is, evaluation within Manipulate only occurs when I want to. Specifically, I have the code

s = {None};
Button["Start",
 f[aa_, oo_, pp_] := CreateDialog[Column[{
     Manipulate[
      frame = Refresh[ListPlot[RandomInteger[{1, 100}, a]], 
        Sequence @@ s],
      Control[{{a, 1, "a"}, 0, 100000, 1, Appearance -> "Labeled"}],
      Button["Simulate", s = {}; s = {None}]]
     }], Modal -> True, WindowTitle -> "Simulation"];
 f[Unevaluated@a, Unevaluated@o, Unevaluated@p]]

which after clicking 'Start', leads to the popup window

enter image description here

Changing the values a does not automatically updates the plot, only when I click on Simulate.

For higher values of the parameter (a=100000, for example), plotting takes a bit longer and since I'm on a CreateDialog environment, the only indicator of ongoing evaluation is the following (I'm using Windows 10)

enter image description here

I wonder if it's possible to implement a small "loading" animation or progress indicator in the popup window itself. For example, replace the plot by that while it's being evaluated and inactivate the 'Simulate' button.

I am aware of Monitor and ProgressIndicator, but I can't seem to make it work in the CreateDialog environment. Any ideas?

$\endgroup$
  • $\begingroup$ 1. Does it need to be something animated or could you replace the plot with a static message like "Please wait"? 2. Is the simulation button essential or are you just trying to avoid continuous updates while the slider is being moved? $\endgroup$ – Simon Woods Dec 9 '19 at 22:46
3
+50
$\begingroup$

I tend to use DynamicModule instead of Manipulate

Also, just for fun, I decided to overkill this problem to demonstrate how this kind of thing can be done extensibly and flexibly.

Options[MySimulation] =
  {
   "RangeMin" -> 1,
   "RangeMax" -> 100,
   "PointsMin" -> 0,
   "PointsMax" -> 100000
   };
Format[MySimulation[Dynamic[state_Symbol], ops : OptionsPattern[]]] :=

  Interpretation[
   DynamicModule[
    {
     frame, 
     simulate,
     plot,
     a,
     display,
     min = OptionValue[MySimulation, {ops}, "RangeMin"], 
     max = OptionValue[MySimulation, {ops}, "RangeMax"],
     pmin = OptionValue[MySimulation, {ops}, "PointsMin"],
     pmax = OptionValue[MySimulation, {ops}, "PointsMax"]
     },
    Panel[
     Grid[
      {
       {"a", Manipulator[Dynamic[state["Value"]], {pmin, pmax}]},
       {Button["Simulate", simulate[state["Value"]], Method -> "Queued"], 
        SpanFromLeft},
       {Panel[Dynamic[display], Background -> White], SpanFromLeft}
       }
      ]
     ],
    Initialization :> {
      If[! AssociationQ@state,
       state = <|"Value" -> 1|>;
       ],
      simulate[a_] :=
       (
        display =
         Pane[
          Row@{"Calculating", ProgressIndicator[Appearance -> "Ellipsis"]},
          ImageSize -> {500, 500/GoldenRatio}
          ];
        Pause[1];
        state["Data"] = RandomInteger[{min, max}, a];
        display = plot[state["Data"]];
        ),
      plot[data_] :=
       ListPlot[data, ImageSize -> 500],
      If[MissingQ@state["Data"], 
       simulate[state["Value"]]
       ]
      }
    ],
   MySimulation[Dynamic[state], ops]
   ];
MySimulation[] :=
 With[{state = Unique[`MySimulation`state]}, 
  SetAttributes[state, Temporary];
  MySimulation[Dynamic[state]]
  ]

In this I 1) bind my data to a state symbol which I stores all the simulation state 2) I make sure that gets passed through to a simulation object 3) this object displays as the simulation control, but retains a convenient InputForm and 4) I make sure to feed in my options in a nice way.

Lots of things you can build off of this, but I think it's a cute template if you don't do this kind of thing often.

Here's a demo:

MySimulation[]

enter image description here

% // InputForm

MySimulation[Dynamic[Global`MySimulation`state$223319]]

Global`MySimulation`state$223319//Short

<|Value->54200.,Data->{68,98,90,56,76,59,59,86,<<54184>>,10,57,66,52,68,74,99,19}|>

And when you press the button it "thinks" for a second and looks like:

enter image description here

$\endgroup$

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.