MathGroup Archive 2008

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Nested DynamicModule and EventHandler

  • To: mathgroup at smc.vnet.net
  • Subject: [mg92437] Re: [mg92399] Nested DynamicModule and EventHandler
  • From: John Fultz <jfultz at wolfram.com>
  • Date: Tue, 30 Sep 2008 21:52:45 -0400 (EDT)
  • Reply-to: jfultz at wolfram.com

There are two fundamentally different ways of doing scoping which you'remixing 
up here.  Lexical scoping literally searches the right-hand side for a symbol 
and replaces it before evaluation.  Dynamic scoping temporarily substitutes a 
new value for the existing variable in the global namespace (in a sense, 
generating a completely new environment where that variable now has the new
value).

Paste tutorial/BlocksComparedWithModules into the help viewer input field to see
a better explanation of this.

DynamicModule uses lexical scoping, but your buttonD implementation suggests
that you're hoping for dynamic scoping.  There is no such thing as DynamicBlock 
because we really couldn't do things any other way without Dynamics 
contaminating the global namespace in the kernel, potentially causing bad 
interactions between multiple Dynamics or a Dynamic and a Shift+Enter evaluation 
one might otherwise expect to be independent.

Here's some changes to your code which make things work as you expect...

SetAttributes[buttonD, HoldAll]
buttonD[b_, c_] := 
 Button["button D", active := fd[b, c], ImageSize -> Automatic] 

SetAttributes[fd, HoldAll]
fd[b_, c_] := 
 Column[{EventHandler[
    Dynamic[Graphics[{Circle[c, 0.1], b}, 
      PlotRange -> {{-1, 1}, {-1, 1}}, Frame -> True]], 
    "MouseDown" :> (c = MousePosition["Graphics", {}];
      AppendTo[b, Point[c]])], Row[{"b ", InputField[Dynamic[b]]}]}]

Then change the call to buttonD in the parent evaluation to take the arguments b 
and c (i.e. the DynamicModule variables).  So, a couple more explanations 
here...

* The DynamicModule wrappers you had were superfluous, so I removed them.
* The HoldAll setting is necessary because you have functions like Dynamic and 
AppendTo that really want access to the original DynamicModule variables.  
Typically, Mathematica evaluation order would cause the arguments of buttonD and
fd to be fully evaluated before the function ever saw them.  I.e., it would be 
equivalent to calling buttonD[{Green, Point[{-.25,-.25}]}, {0,0}].  By declaring 
the functions HoldAll, I'm instructing Mathematica to not do such a 
substitution, and instead pass the DynamicModule variables into the function
body unevaluated.

That's quite a crash course in evaluation ordering and scoping.  I hope you
found my explanation helpful.

Sincerely,
 
John Fultz
jfultz at wolfram.com
User Interface Group
Wolfram Research, Inc.


On Tue, 30 Sep 2008 07:37:31 -0400 (EDT), Hugh Goyder wrote:
> I use modules to localise variables and to simplify code. In
> attempting to understand the additional complications of using
> DynamicModule in version 6 I am trying to sort out how to work with
> buttons, modules and EventHandlers.
>
> Below three of my buttons, with increasing complexity, work but the
> fourth, buttonD, fails. I can click points onto the graphic with the
> set-up of buttonC but not with buttonD.  I am trying to get
> communication between the parent and child modules where points are
> introduced into the child module using the EventHandler. Thus with
> buttonD pressed clicking on the graphic should produce an additional
> primitive in the list maintained by the parent module. What is the
> correct way to do this?
>
> Thanks Hugh Goyder
>
>
> ClearAll[buttonA, buttonB, buttonC, buttonD];
> buttonA[] := DynamicModule[{}, Button["button A", active := fa[],
> ImageSize -> Automatic]];
> buttonB[] := DynamicModule[{}, Button["button B", active := fb[],
> ImageSize -> Automatic]];
> buttonC[] := DynamicModule[{}, Button["button C", active := fc[],
> ImageSize -> Automatic]];
> buttonD[] := DynamicModule[{}, Button["button D", active := fd[],
> ImageSize -> Automatic]];
>
> ClearAll[fa, fb, fc, fd];
> fa[] := DynamicModule[{}, Plot[x^2, {x, -2, 2}]];
> fb[] := DynamicModule[{a = 5}, Column[{Slider[Dynamic[a], {0, 10}],
> Dynamic[Plot[Sin[a*x], {x, 0, 2*Pi}]]}]];
> fc[] := DynamicModule[{b = {}, c = {0.5, 0.5}},
> Column[{EventHandler[Dynamic[Graphics[{Line[{{0, 0}, c}], b},
> PlotRange -> {{0, 1}, {0, 1}}, Frame -> True]],
>
> "MouseDown" :> (c = MousePosition["Graphics", {}];
> AppendTo[b, Point[c]])],
> Row[{"b ", InputField[Dynamic[b]]}]}]];
> fd[] := DynamicModule[{},
> Column[{EventHandler[Dynamic[Graphics[{Circle[c, 0.1], b},
> PlotRange -> {{-1, 1}, {-1, 1}}, Frame -> True]],
>
> "MouseDown" :> (c = MousePosition["Graphics", {}];
> AppendTo[b, Point[c]])],
> Row[{"b ", InputField[Dynamic[b]]}]}]]
>
> DynamicModule[{active = Graphics[{}], a, g,
> b = {Green, Point[{-0.25, -0.25}]},
> c = {0, 0}},
> Column[{Row[{buttonA[], buttonB[], buttonC[], buttonD[]}],
> Dynamic[active], Row[{"b (outer)", InputField[Dynamic[b]]}],
> Row[{"c ", InputField[Dynamic[c]]}],
> Row[{"active ", InputField[Dynamic[active]]}]}]]




  • Prev by Date: Re: Nested DynamicModule and EventHandler
  • Previous by thread: Re: Nested DynamicModule and EventHandler
  • Next by thread: Re: Re: Solving nonlinear inequality constraints