2
$\begingroup$

Consider this (edit: Pause[3] represents some long computation the button should do):

Manipulate[Dynamic@output, Button["do", 
    output = "Paused..."; FinishDynamic[]; Pause[3]; output = "done"]]

This works in that we see the Paused message briefly. But it uses a global variable output.

1) If you take out the FinishDynamic[], or the first Dynamic@ it does not work.

2) If you add a {output,ControlType->None} to the Manipulate, it does not work.

3) Similarly for wrapping it all within a DynamicModule[{output},]

Is there a better way to update the output of a Manipulate from within a Button? I'd like to avoid eg Refresh every second since the recalculation will in principle happen very rarely.

$\endgroup$

2 Answers 2

3
$\begingroup$

I don't think that anything is wrong with Michaels answer but I wanted to mention that the following does what I think you expect in a somewhat more straightforward way:

Manipulate[
 Dynamic[output, TrackedSymbols :> {output}],
  Button["do", output = "Paused..."; FinishDynamic[]; Pause[3]; 
   output = "done",
   Method -> "Queued"
 ],
 {output, ControlType -> None}
]

the trick is to add the TrackedSymbols option to Dynamic. I did additionally add the Method->"Queued" option to the button, which is not necessary for this example to run but certainly is a good idea once your calculation (or Pause) takes or could take more than 6 second (or more precisely what DynamicEvaluationTimeout is set to).

I would also like to mention that I think once you start to build an interface where you want precise control about when which part of the code is evaluated it might actually become simpler/more straightforward to use the lower level "dynamic language" constructs directly instead of manipulating Manipulate, e.g.:

DynamicModule[{output = ""},
  Panel[
    Column[{
      Button["Do",
        output = "Paused...";
        Pause[3];
        output = "Done.";
        ,
        Method -> "Queued"
      ],
      Panel[Pane[Dynamic[output, TrackedSymbols :> {output}], {100, 50}]]
    }]
  ]
]
$\endgroup$
3
  • $\begingroup$ Both your and Michael's solutions are perfect. I particularly like how this one requires fewer edits to the example code, and the self-TrackedSymbols trick is an interesting one to know for the future. Thanks! $\endgroup$ Feb 20, 2015 at 15:43
  • $\begingroup$ @PhilipMaymin: thanks for the accept. I would like to draw your attention to the Method->"Queued" setting, you almost certainly will find that necessary for your real problem... $\endgroup$ Feb 20, 2015 at 16:02
  • $\begingroup$ Yes, I use that of course, thank you. Just left it out of the question for brevity, probably too much brevity. :) Thanks again. $\endgroup$ Feb 20, 2015 at 20:46
1
$\begingroup$

I'm not entirely sure what you're after. Here are two ideas. The first one preserves the waiting 3 seconds. If that's not important, see further down.

Manipulate[output,
 {{output, "new", ""},
  DynamicModule[{timer = Infinity},
    Button[
     DynamicWrapper["do", 
      If[Clock[{0, Infinity}] >= timer + 3, output = "done"]],
     output = "Paused..."; timer = Clock[{0, Infinity}]]] &},
 TrackedSymbols :> {output}]

I used something like {{update, 0}, Button["Update", update++] &} in this answer. If trial appears in the body of the Manipulate, even just as update;. Here's an example:

Manipulate[update;
 RandomReal[],
 {{update, 0}, None},
 Button["Update", update++]
 ]

Update - Third example: I'm still not sure how Pause[3] and output are to be integrated into the Manipulate. Here's another idea:

Manipulate[
 If[output === "Paused",
  output = (Pause[3]; "done")];
 Dynamic@output,
 {{output, "done"}, None},
 Button["do", output = "Paused"]]
$\endgroup$
6
  • $\begingroup$ I'm trying to understand your first one. The Pause was just to represent some long computation. Where would I put the bulk of such code in your example? $\endgroup$ Feb 20, 2015 at 3:10
  • $\begingroup$ Also, I like the Button& approach, but when I try Manipulate[Dynamic@output, {{output, "start",}, Button["do", output = "Paused..."; FinishDynamic[]; Pause[3]; output = "done"] &}] it never displays "Paused" $\endgroup$ Feb 20, 2015 at 3:10
  • $\begingroup$ I don't know DynamicWrapper very well but it seems to essentially refresh every second? For example running counter = 0; Button[DynamicWrapper["hi", counter++], Print@counter] and pressing the button gives large numbers. $\endgroup$ Feb 20, 2015 at 3:14
  • $\begingroup$ @PhilipMaymin I think the first solution above is not what you're after, if Pause represents any function. -- The Button (2nd comment) never displays "Paused" because the whole computation is completed before the Front End is notified of any updates. -- The counter++ is executed every time counter changes value, similar to Dynamic[counter++]; and since it changes value every time counter++ is executed, you get an infinite loop. $\endgroup$
    – Michael E2
    Feb 20, 2015 at 3:27
  • $\begingroup$ Your updated solution is perfect! Great solution. Thanks very much. $\endgroup$ Feb 20, 2015 at 3:42

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.