From: Guido Tripaldi on 4 Mar 2010 05:32 consider this example: (* define a function that ask the user for choosing values *) chooseItems[itemsList_, defaultItems_] := Module[ {selectedItems}, selectedItems = defaultItems; ChoiceDialog[ CheckboxBar[Dynamic[selectedItems], itemsList] ]; Return[selectedItems] ] (* some defaults inits *) myItemsList = {1 -> "A", 2 -> "B", 3 -> "C"}; myDefaultItems = {2}; mySelectedItems = {}; (* call the function from a Button *) Button["choose", mySelectedItems = chooseItems[myItemsList, myDefaultItems], Method -> "Queued"] (* display result *) Dynamic[mySelectedItems] if you call (evaluate) the chooseItems[itemsList_, defaultItems_] function directly, it works as expected, but if you call it as a Button action, the CheckBoxBar view isn't updated according to the box clicked (but the returned value will be set correctly). Now, in the function definition, making global instead of local the "selectedItems" var, all will works as wanted : chooseItems[itemsList_, defaultItems_] := Module[ {}, (* moved to global *) selectedItems = defaultItems; ChoiceDialog[ CheckboxBar[Dynamic[selectedItems], itemsList] ]; Return[selectedItems] ] myItemsList = {1 -> "A", 2 -> "B", 3 -> "C"}; myDefaultItems = {2}; mySelectedItems = {}; selectedItems = {}; (* global *) Button["choose", mySelectedItems = chooseItems[myItemsList, myDefaultItems], Method -> "Queued"] of course, this workaround isn't very desirable as "When you write a program in Mathematica, you should always try to set it up so that its parts are as independent as possible". Even after reading the really interesting answer by John I don't find a different way around, nor I understand if this undesirable side effect of Dynamics is somewhat predictable by an average Mathematica user (like myself) or to understand (and to be able to resolve) it, requires a deeper study of the insides of Mathematica.. thanks in advance, Guido Il giorno 01/mar/2010, alle ore 10.42, John Fultz ha scritto: > On Sun, 28 Feb 2010 04:53:10 -0500 (EST), Albert Retey wrote: >> Hi, >> >>> Synchronous Dynamics (which is what you get by default) are stop-the- >>> world sorts >>> of evaluations. When they're running, any ongoing kernel computation is >>> completely halted, and the Dynamic evaluation is completely >>> uninterruptible. >>> Even another Dynamic evaluation cannot interrupt it. Likewise, the >>> front end is >>> locked into a mode where it can only respond to a very limited number >>> of events >>> while it awaits the resolution of the Dynamic. >>> >>> For this reason, all synchronous Dynamics are evaluated, by default, >>> with a >>> TimeConstrained wrapper using a time derived from the >>> EvaluationDynamicTimeout >>> option in the kernel. This option can be tailored on a per-Dynamic >>> basis if you >>> like using the Style[] function to set the option. The goal is that >>> absolutely >>> no Dynamic should be allowed to lock up the front end and kernel in >>> such away >>> that they appear unresponsive to users. >>> >>> ChoiceDialog[], or any other function which awaits user input, causes >>> the kernel >>> to wait for results, but doesn't stop the timer in TimeConstrained[] >>> from >>> expiring. >>> >>> Any Dynamic which you expect to take a long time should be using >>> SynchronousDynamic->False. This causes the Dynamic to be put into the >>> same >>> queue as Shift+Enter evaluations, and it can take as long as you want. >>> So it's >>> not evaluated urgently, but there will be no need for it to evaluate >>> urgently, >>> either. >>> >>> Incidentally, the same thing applies with Method->{"Queued"} (as >>> opposed to >>> "Preemptive") in Button and ActionMenu. >>> >> I hear your words, but probably don't understand.... >> >> While my experience shows that Method->"Queued" in Buttons and >> ActionMenus fixes any problems with kernel blocking dialogs, using >> SynchronosUpdating->False (I guess that's what you meant) does not help, >> at least with my version 7 on Windows XP this also hangs: >> >> DynamicModule[{planets, x, habitantq}, >> planets = {"Mercury", "Venus", "Earth"}; >> x = First[planets]; >> Column[{ >> PopupMenu[Dynamic[x, {x = #; >> If[StringMatchQ[x, "Earth"], >> habitantq = ChoiceDialog[Column[{"Do you live on earth?"}], >> {"Yes" -> True, "No" -> False}]]} &, >> SynchronousUpdating -> False], planets], >> Dynamic[x], >> Dynamic[habitantq] >> }]] >> >> and so does this: >> >> DynamicModule[{planets, x, habitantq}, >> planets = {"Mercury", "Venus", "Earth"}; >> x = First[planets]; >> Column[{ >> PopupMenu[Dynamic[x, {x = #; >> If[StringMatchQ[x, "Earth"], >> habitantq = ChoiceDialog[Column[{"Do you live on earth?"}], >> {"Yes" -> True, "No" -> False}]]} &, >> SynchronousUpdating -> False], planets], >> Dynamic[x, SynchronousUpdating -> False], >> Dynamic[habitantq, SynchronousUpdating -> False] >> }]] >> >> is there any known way to get something like this working? >> >> regards, >> >> albert > > Sorry...yes, of course I meant SynchronousUpdating. > > You raise an important issue which I've never taken the opportunity to > completely clarify on this group (although I think I touched on it briefly a > couple of months ago). The issue is that there are really two different kinds > of Dynamics. They share so many properties that many people really don't need > to understand the difference, but there are a small number of ways in which they > are distinctly different. > > We don't have official names for these things really, so I'll make up some names > which you may or may not like, but probably shouldn't consider official Wolfram > lingo. I'll refer to "instancing" Dynamics and "controller" Dynamics. > > An instancing Dynamic is one which creates an area on the screen containing some > contents. MakeBoxes, when run on such a Dynamic, turns it into a DynamicBox. > If such a Dynamic were unable to resolve, you'd see a gray box on the screen > representing the area it would have taken (with a few exceptions...a Dynamic > inside of a graphic might not show the gray box). You can think of an > instancing Dynamic as an output-only zone. You can't somehow click on an > instancing Dynamic and directly affect its properties...not without some > mechanism of causing additional evaluations. Therefore, the second argument of > Dynamic is meaningless to an instancing Dynamic. > > A controller Dynamic is one which does not represent an area on the screen, but > merely sets the value of another thing which displays on the screen. For > example, the Dynamic argument of Slider, Checkbox and Locator. Any coordinates > of a graphics primitive specified with Dynamic are using a controller Dynamic. > Dynamics on the right-hand side of front end options are also controller > Dynamics. MakeBoxes of such a Dynamic returns Dynamic, not DynamicBox. It > doesn't return DynamicBox because what's important is the *value* of the Dynamic > result, not its appearance. The appearance of a Slider is always as a slider; > the Dynamic argument merely controls the value the slider appears to be set to. > In nearly all cases (excepting the rhs of FE options), a controller Dynamic > represents a two-way interface. It controls the display of its value, but also > accepts the setting of new values through some interactive means, which makes > the second argument of Dynamic a very meaningful concept here. > > As I said, most of the functionality of Dynamic is shared between both types. > But here's a list of things (well, the things I could think of...might not be > complete) which you can only meaningfully use within one of the types... > > * Second argument of Dynamic - controller Dynamic > * ShrinkingDelay option of Dynamic - instancing Dynamic > * SynchronousUpdating option of Dynamic - instancing Dynamic > > The first two limitations are conceptual and really quite necessary. If an > instancing Dynamic allowed you to change it, it would be an InputField (with > Appearance->None). There are many times when that's really not what you want, > and if it is, you should simply use InputField instead. ShrinkingDelay just > isn't meaningful for an object which has no concept of size, such as a > controller Dynamic. > > SynchronousUpdating is a bit trickier. There are extra difficulties with > implementing an asynchronous version of controller Dynamic (particularly, having > a control which is in an "unknown" state for a possibly long period of time). > And that extra difficulty is exactly why it's not implemented in controller > Dynamics for now. But one can imagine that this as a meaningful concept, and so > this might change for future versions. > > But for now, SynchronousUpdating only works for instancing Dynamics. Which > means that controller Dynamics are generally locked into what I referred to > before as "stop-the-world" evaluations. > > Note that it's generally not necessary to implement things this way, though. > You can make an controller Dynamic which sets immediately, and then triggers an > instancing Dynamic that operates asynchronously. Or, perhaps a controller > Dynamic isn't necessary at all...but instead some sort of Button or ActionMenu > item. > > Here's an interesting concept I worked up for someone recently which you might > find interesting...an ActionMenu which works like a PopupMenu by virtue of > containing an instancing Dynamic for the appearance. The simplest case... > > DynamicModule[{x = 1}, > ActionMenu[Dynamic[x], {1 :> (x = 1), 2 :> (x = 2), 3 :> (x = 3)}]] > > which is equivalent to > > DynamicModule[{x = 1}, PopupMenu[Dynamic[x], {1, 2, 3}]] > > except that it guarantees the evaluation of the "x =" statements every time you > choose the menu, rather than only when 'x' would change. Your example could > very easily be reformulated using such a mechanism. Then setting > Method->"Queued" would allow you to put things such as ChoiceDialog[] in the > actions. > > Sincerely, > > John Fultz > jfultz(a)wolfram.com > User Interface Group > Wolfram Research, Inc. > --- Guido Tripaldi imho.gtripaldi.it |