I need to perform a long action with a button. I tried setting the DynamicEvaluationTimeout
, but it seems it doesn't work for me. So I want to try using several buttons to compute pieces of the whole task and here's where my problem starts:
How to tell Mathematica that a button should be pressed (or have its action performed) without actually pressing the button by user? Is there a way to emulate such a thing from within the code?
I need to use the preemptive link, so Method -> "Queued"
is not the solution I'm looking for.
1 Answer
One can come up with some messy method to evaluate a front-end button programmatically, but I think it is easier to separate the button functionality from the button itself, as listenerButtonFunction[]
. Here I introduce a timer button that, if pushed, counts down simulating a long calculation. When it finishes, it switches the flag active
to True
. The second button has a Dynamic
wrapper and thus it listens to the changes made to active
: whenever active
is set to True
, the appearance of the listener button is changed. Now the functionality of the listener button is separated, so we can call it right after setting active = True
in the first button, simulating the manual push of the listener button.
Note that I only used Method -> "Queued"
to see how the timer goes down. If omitted, the listener still will be activated in due time. Also, the listener button can be pushed on its own.
active = False;
n = 0;
listenerButtonFunction[] := Print["Listener activated"];
Row@{Button["Timer", active = False; n = 100;
Do[Pause[.02]; n = n - 1, {i, 100}]; active = True;
listenerButtonFunction[], Method -> "Queued"], Spacer@5, Dynamic@n}
Dynamic@If[active,
Button["Listener: ACTIVE", active = False,
Appearance -> {Automatic, "Pressed"}],
Button["Listener: inactive", listenerButtonFunction[],
Appearance -> Automatic]
]
Update
The following method creates a button that is wrapped in Dynamic
that listens to the state change of the switch active
, which can be changed by either hitting the second button or waiting for the calculation of the first button to finish (just like above). The function of this second button is actually performed by the Dynamic
wrapper whenever active
becomes True
. The Print
statement is redirected by default to the Messages window, but if listenerFunction
is e.g. a long calculation that does not print anything, this shouldn't matter.
active = False; n = 0;
listenerFunction[] := Print["Listener pushed"];
Row@{Button["First", active = False; n = 100;
Do[Pause[.005]; n = n - 1, {i, 100}]; active = True;,
Method -> "Queued"], Spacer@5, Dynamic@n}
Dynamic[If[active, listenerFunction[]];
Button[If[active, "active", "inactive"], active = ! active]]
-
$\begingroup$ That's an interesting approach, but I can't see it working for me. $\endgroup$– DaroslavCommented Oct 27, 2012 at 10:35
-
$\begingroup$ @Daroslav Where does it fail? Perhaps set the
Pause
value to something smaller? Make sure that you evaluate it with a fresh kernel. $\endgroup$ Commented Oct 27, 2012 at 10:40 -
$\begingroup$ I'm sorry, I pressed enter too soon. Here's the rest of my comment: I want to use my button to run an animation with a dynamic
Graphics
object. Since it's long, the preemptive link times out. The good news is, I can split it into parts. So I need aButton
, that will do a part of the job, and then calls itself (or a differentButton
) to do a part of the rest of the job, and so on. $\endgroup$– DaroslavCommented Oct 27, 2012 at 10:42 -
$\begingroup$ @Daros You could put the "rest of the job" into
listenerButtonFunction
, and you can link an infinite number of buttons in this way. $\endgroup$ Commented Oct 27, 2012 at 11:13 -
$\begingroup$ I just thought I could, guess I needed some time to digest your idea ;) Thanks, that's really helpful, I'll try to adapt that. $\endgroup$– DaroslavCommented Oct 27, 2012 at 11:31
Read the FAQs
! 3) When you see good Q&A, vote them up byclicking the gray triangles
, because the credibility of the system is based on the reputation gained by users sharing their knowledge. ALSO, remember to accept the answer, if any, that solves your problem,by clicking the checkmark sign
` $\endgroup$Method->"Queued"
. I think you should explain better what you try to do and why -- probably without preemptively excluding possible solutions. And remember: providing an example (especially if it demonstrates what does not work) for people to play with will always help a lot to get better answers. $\endgroup$