开发者

question on dynamic, SynchronousUpdating, inside Manipulate

开发者 https://www.devze.com 2023-04-01 14:07 出处:网络
I am trying to see if I can make my own simulation loop inside Manipulate as I am not happy with either the Trigger control or using Tasks (both have problems and limitations for what I\'d like to do)

I am trying to see if I can make my own simulation loop inside Manipulate as I am not happy with either the Trigger control or using Tasks (both have problems and limitations for what I'd like to do).

So, I was trying to see if I can make my own c开发者_运维技巧ontrol loop, this way I have better control of things, where by clicking on a 'run' button, simulation loop will start until a 'stop' button is clicked.

A basic problem is that Manipulate times out after 5 seconds even though I am using SynchronousUpdating -> False. i.e. when I click the 'run' button, I start a loop (with some Pause[] in it of course), and will then update something in the loop. This works fine, but after 5 seconds, the loop stops on its own, since Manipulate decided to time out.

I might be misunderstanding something basic here. I show below simple example:

Manipulate[
Dynamic[Refresh[Text@x,TrackedSymbols->{x}]],

{{x,0},ControlType->None},
{{running,True},ControlType->None},

Button[Text["play"],
  {
   running=True,
   While[running,
     x+=1;
     FinishDynamic[];
     Pause[0.1]
   ]
  }],

Button[Text["stop"],
    running=False
  ],

TrackedSymbols->{None},
SynchronousUpdating->False,
SynchronousInitialization->False
]

When running the above, it always stops around count 58 or so, which is about 5 seconds, the time-out value for Manipulate

question on dynamic, SynchronousUpdating, inside Manipulate

Outside Manipulate, it works ok as expected:

x = 0;
Dynamic[Refresh[x, UpdateInterval -> 0.001]]

Do[
 (
  x += 1;
  FinishDynamic[];
  Print[x];
  Pause[0.01]
  ), {i, 0, 200}
 ]

I can make the count above as large as I want, no problem.

So, it seems a configuration option for Manipulate, but I am now not able to find now which option it is I need to use for this to work.

Thanks

Update

Using the Method->"Queued" as given below by Simon, now the loop works. But there are problems with this method: I can not use Mathematica while the Button is running, even with large Pauses in the loop, as it blocks the whole front end. It behaves as if the button is pressed all the time. So, this idea is out of question to use. Well, it was something to try.

btw, this is a good time to mention this, I found that using cell of type 'code' instead of the default 'input' causes many crashes in the kernel. Just tried cell type 'code' and after few clicks on the button, kernel crashed:

question on dynamic, SynchronousUpdating, inside Manipulate

So I no longer use cells of type 'code'.

Back to the drawing board.

Update 2: 8/29/11, 6 PM

Using Mathematica 8.0.1, on windows 7, SP1, intel pc, here is the code that crashes it when using "code" cell

Manipulate[
Dynamic[Refresh[Text@x,TrackedSymbols->{x},UpdateInterval->0.005]],

{{x,0},ControlType->None},
{{running,True},ControlType->None},

Button[Text["play"],
  {
   running=True,
   While[running,
     x+=1;
     FinishDynamic[];
   ]
  },Method->"Queued"],

Button[Text["stop"],
    running=False
  ],

TrackedSymbols->{None},
SynchronousUpdating->False,
SynchronousInitialization->False
]

May be someone can try the above? Had to click on start/stop few times to get it to crash.

I can reproduce this.

question on dynamic, SynchronousUpdating, inside Manipulate

Update 9/2/11

on new answer: It looks Simon version (second one below) seems faster on my PC, Mathematica 8.0.1. I started both at the same time, and the Simon version seems to run faster (counter runs faster).

screen shot:

question on dynamic, SynchronousUpdating, inside Manipulate


I think that it's actually the Button that is timing out, not the Manipulate.

To quote the Options > Method section of the Button docs,

By default, button functions are evaluated on a preemptive link, which times out after 5 seconds:

Set the option Method -> "Queued" for the button and everything works as expected.


You might get better results if you let Manipulate control the "looping":

Manipulate[
  If[running, x++, x]
, {{x, 0}, ControlType -> None}
, {{running, True}, ControlType -> None}
, Button["play", running = True]
, Button["stop", running = False]
]

I presume that Manipulate is being used here to support further controls within the real application. If not, then DynamicModule would be sufficient.

DynamicModule[{x = 0, running = True}
, Column[
    { Button["play", running = True]
    , Button["stop", running = False]
    , Dynamic[If[running, x++, x]]
    }
  ]
]

The following example animates a moving disk using this technique:

DynamicModule[{t = 0, running = True}
, Column[
    { Button["play", running = True]
    , Button["stop", running = False]
    , Dynamic[
        If[running, t++, t] /.
          t_ :> Graphics[Disk[{Cos[t/10], Sin[t/10]}]
                       , PlotRange -> {{-3,3},{-3,3}}
                       , Axes -> True
                       ]
      ]
    }
  ]
]
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号