Message Boards Message Boards

GROUPS:

How to force Dynamic Clock in a Button to wait for mouse click to start?

Posted 3 months ago
394 Views
|
0 Replies
|
0 Total Likes
|

Abstract

My task sounds simple and straight forward but not all is as it first appears. I just need a Button that waits to be Clicked before displaying a countdown timer in the label. Button will eventually do a lot more which I have coded before including evaluation control however everything I tried to stall countdown just doesn't work. The Clock in countdown always starts when the Button is created even if the current value of label isn't displayed as demonstrated in Button samples given below.

I even tried wrapping and embedding Button with multiple layers of mouse EventHandlers which worked with styles like Background but failed completely on countdown (did not update label). I'm almost positive I did something wrong. Unfortunately that code was lost. Please help me find a solution. I have been trying to solve this off and on for months.

countdown (Clock)

Here is my latest iteration of countdown. As you can see it's wrapped in an anonymous Function which has attributes HoldAll (should not Evaluate until all arguments are provided) in an attempt to force the Clock in countdown to wait on a mouse event. A few of the various Buttons attempted are shown afterwards.

countdown =
  Function[{s, n}, Dynamic[s - Clock[{0, s, 1}, s, n]]];
(* demo countdown timer *)
Row[{"almost bare naked countdown \[Rule] ", countdown[10, 1]}]

Button 0: Global

This is the only Button not wrapped in a DynamicModule and in which label x is set to an intermediary variable named timer (this variable is only used here) so that Clock in countdown can be observed to start without a Click event (Evaluate Cells may need to be executed more than once). Immediate Evaluation (before mouse event) is not how a Button is supposed to behave.

Quiet@ClearAll[x];
Row[{"Global label (x) set to intermediate variable (timer) \[Rule] ", 
  Button[Dynamic[x = timer], (timer := countdown[60, 1]) &, 
   ImageSize -> {75, 30}]}]

Button 1: Click

After momentary wait click Button. If less than 60 Clock in countdown did not wait for Click event. Also note that Clock continued to run dynamically despite not displaying updated value in label x before Click event. This even continues to run if Cell containing Button is scrolled out of view. This is not how Dynamic is supposed to work. Although AutoAction -> False is the default setting it is explicitly set for reasons which will become clear in Button 2: (Hover).

DynamicModule[{x}, 
  Row[{"DynamicModule Button with regular Click \[Rule] ", 
    Button[Dynamic[x, (#) &, 
      Initialization :> (x = "wait 5s then Click")], (x := 
        countdown[60, 1]) &, ImageSize -> {150, 30}, 
     AutoAction -> False]}]]

Button 2: Hover

After momentary wait hover Button. If less than 60 Clock in countdown did not wait for Hover event. Again note that this Button 2 (Hover) exhibits all the same dynamics as Button 1 (Click). That is because AutoAction does not supercharge Evaluation. The only thing it does is emulate a Click event with Hover.

DynamicModule[{x}, 
 Row[{"DynamicModule Button with Hover \[Rule] ", 
   Button[Dynamic[x, (#) &, 
     Initialization :> (x = "wait 5s then Hover")], (x := 
       countdown[60, 1]) &, ImageSize -> {150, 30}, 
    AutoAction -> True]}]]

Why Stress Click vs. Hover?

I stress the role of option AutoAction because I posted similar questions before at mathematica.stackexchange.com...

  1. https://mathematica.stackexchange.com/questions/253172/please-help-with-dynamic-autosave-button-that-only-halfway-works
  2. https://mathematica.stackexchange.com/questions/253544/my-dynamic-button-evaluates-as-soon-as-its-created-how-do-i-stop-this-behavior

but the few well-meaning good folks who tried to help only provided halfway good but mostly unsatisfactory answers. They were under the mistaken impression that AutoAction would control Clock evaluation or that there was nothing wrong with my code. I believe they didn't wait long enough after Button was rendered to observe the immediate invocation of countdown without a mouse event. It was mostly my bad for not properly setting up demos. That is what I tried to avoid here.

Closing Thoughts

The official Wolfram Documentation isn't very clear on how Clock evaluation is supposed to work. I don't believe there is anything wrong with Clock but it could have been designed with better evaluation control. However it is absolute on how Dynamic and Button are designed to work. Dynamic objects should never update when not in view (unless contained in DynamicWrapper) and Button should never permit evaluation of expression unless invoked by a mouse or similar event. I believe these are bugs with both and Button and Dynamic. However I still have faith that there is a simple work-around (without injecting code with spaghettis-like low-level procedural loops and routines) using some of the deeper Evaluation controls provided by Mathematica.

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract