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$ Commented 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$ Commented 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$ Commented 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$ Commented 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$ Commented 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$ Commented 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$ Commented Feb 20, 2015 at 3:27
  • $\begingroup$ Your updated solution is perfect! Great solution. Thanks very much. $\endgroup$ Commented Feb 20, 2015 at 3:42

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.