1
$\begingroup$

I have a dynamic module that contains some basic PopupMenu's and Buttons but also need to use the variables returned from these buttons and PopupMenu's in my nb functions outside of this DynamicModule. Here is the code:

DynamicModule[{var = 1, var2 = 3},
 Dynamic[Column[Join[
  {PopupMenu[pass2Fun1 = Dynamic[var], {1 -> "Return 1", 2 -> "Return 2", 
   3 -> "Return 3"}, ContinuousAction -> True]},
  Switch[var, 1,
   {Button["One", Module[{data = SystemDialogInput["FileOpen"]}, {}], 
   Method -> "Queued"]}, 2,
    {Button["Two", Module[{data2 = SystemDialogInput["FileOpen"]}, {}], 
     Method -> "Queued"], 
     Button["Three",Module[{data3 = SystemDialogInput["FileOpen"]}, {}], 
     Method -> "Queued"]}, 3,
    {Button["Four", Module[{data4 = SystemDialogInput["FileOpen"]}, {}], 
    Method -> "Queued"],
  PopupMenu[pass2Fun2 = Dynamic[var2], {3 -> "choice 1", 4 -> "choice 2", 
    5 -> "choice 3"}, ContinuousAction -> True]}
 ]]], TrackedSymbols :> {var, var2}]]

pass2Fun1 and pass2Fun2 are variables that are needed outside the Dynamic Module, and of course so are the SystemDialogInput variables.

Take for example the If statement code where we can test to see if the variable pass2Fun1 ==1 To run this test place the above Dynamic Module code in a cell and check to see that the variable pass2Fun1 is filled as Global` Then run the If statement code in another cell to see if you get a good printed result.

 If[pass2Fun1 == 1,
 Print["This works", pass2Fun1],
 Print["Broken", pass2Fun1]]

The If statement can not see the variable pass2Fun1==1 but If I print that variable it prints. If I check the context and the context path both are Global`.

Now for the fun Part: In a separate cell evaluate:

pass2Fun1=1; 

Then run the If statement again. Now the code runs fine. I thought we had a solution but further checking revealed this strange behavior. After trying Rojo's code below you will see that this If statement will still not complete. So in both the example code above and Rojo's solution below the result in the If statement test is the same. Rojo's code in the above function:

DynamicModule[{pass2Fun1 = 1, pass2Fun2 = 3}, 
Dynamic[Column[
  Join[{PopupMenu[
     Dynamic[pass2Fun1], {1 -> "Return 1", 2 -> "Return 2", 
      3 -> "Return 3"}, ContinuousAction -> True]}, 
   Switch[pass2Fun1, 
    1, {Button["One", 
      Module[{data = SystemDialogInput["FileOpen"]}, {}], 
      Method -> "Queued"]}, 
    2, {Button["Two", 
      Module[{data2 = SystemDialogInput["FileOpen"]}, {}], 
      Method -> "Queued"], 
     Button["Three", 
      Module[{data3 = SystemDialogInput["FileOpen"]}, {}], 
      Method -> "Queued"]}, 
    3, {Button["Four", 
      Module[{data4 = SystemDialogInput["FileOpen"]}, {}], 
      Method -> "Queued"], 
     PopupMenu[
      Dynamic[pass2Fun2], {3 -> "choice 1", 4 -> "choice 2", 
       5 -> "choice 3"}, ContinuousAction -> True]}]]], 
  TrackedSymbols :> {pass2Fun1, pass2Fun2}]]

My question: What is the best method to get the variable data from another nb a Button or PopupMenu to the functions in a different nb? These nb functions control the generation of results based on the input data and the variables pass2Fun1 & 2 and the SystemDialogInputs. Should all the functions be called inside the DynamicModule or made Global? Even if it's made Global as in the case above, how do I make sure the variable is filled in such a way as to be useful to other functions?

Thanks in advance for the help!

$\endgroup$
8
  • $\begingroup$ It would help to better understand your question to provide a use case example and the behaviour you'd like. For example, what do you mean by "to get the variable data to the functions in a notebook"? $\endgroup$
    – Rojo
    Jul 20, 2012 at 18:41
  • $\begingroup$ Thanks, still have some doubts that I think are relevant. So all you want to do with those variables is have some other interface element display some result of processing them? No need to have them available to write new code and evaluate cells playing with the data? Is the interface element that shows the rsult part of the same cell or from another one? If it's from another one, is it already part of the notebook or generated when you click a button or something (as a dialog would for example?) $\endgroup$
    – Rojo
    Jul 20, 2012 at 20:26
  • 1
    $\begingroup$ If what you want is to simply have them available in a variable, to play around, do further calculations, etc, it makes the most sense to me to store them in a kernel variable. It can be global or it can belong to a context $\endgroup$
    – Rojo
    Jul 20, 2012 at 21:14
  • $\begingroup$ You still don't provide code to test. I'd honestly suggest you edited your question, and at least append at the end whatever code you think should be run (the one you refer to from my answer) so that anyone with a fresh kernel can be sure what to copy and paste to see what you mean $\endgroup$
    – Rojo
    Jul 23, 2012 at 13:23
  • $\begingroup$ The code in my answer not only uses a pass2Fun2 and uses numbers 3,4 and 5 for the choices, so you could never expect it to assign pass2Fun1 the number 1 $\endgroup$
    – Rojo
    Jul 23, 2012 at 13:24

2 Answers 2

4
+100
$\begingroup$

You have your PopupMenu wrong

This is the proper way to write it if you want pass2Fun2 to be kept updated with the PopupMenu selection

PopupMenu[
Dynamic[pass2Fun2], {3 -> "choice 1", 4 -> "choice 2",
5 -> "choice 3"}, ContinuousAction -> True]

This goes for both popups

You had

PopupMenu[pass2Fun2 = Dynamic[var2], ...

After doing those changes you need to remove pass2Fun1 and pass2Fun2 from the local variable list of your DynamicModule if you want to be able to access them from other cells

$\endgroup$
14
  • 1
    $\begingroup$ PopupMenu[pass2Fun1 = Dynamic[var1], ... might be considered unconventional but the global value still updates using the OPs code -- in my notebook anyway. So while this is more elegant, and the way you would normally write this sort of code, what does it actually fix (a question for @RHall) $\endgroup$ Jul 21, 2012 at 0:40
  • 1
    $\begingroup$ @MikeHoneychurch, PopupMenu[pass2Fun1 = Dynamic[var1]... doesn't keep the global up to date. But the global, in StandardForm displays as the dynamic value of var1 which is local to a different cell. So as long as the cell doesn't "resynch" with the kernel, it maay work visually, but I think that's playing with fire $\endgroup$
    – Rojo
    Jul 21, 2012 at 0:42
  • 1
    $\begingroup$ @MikeHoneychurch the OP, for example, couldn't use the global as a parameter to another function (because it was actually a Dynamic[var] and not a value), so he got confused. Then he tested assigning pass2Fun1=1 manually, but now could never get the PopupMenu to ""update"" pass2Fun1 any more dynamically $\endgroup$
    – Rojo
    Jul 21, 2012 at 0:44
  • $\begingroup$ @RHall, the Popup was changing the local "var", but doing nothing to pass2Fun1. But pass2Fun1 was linked visually to the "var" so it appeared to more or less work fine $\endgroup$
    – Rojo
    Jul 21, 2012 at 0:46
  • $\begingroup$ @Rojo I see. yes very confusing. $\endgroup$ Jul 21, 2012 at 0:48
3
$\begingroup$

This answer maybe redundant, if not it may clarify what is required or not.

This is a minimal function that creates a dialog holding a popup which is linked to a Dynamic kernel variable without the use of Module or DynamicModule.

ff[] := (pup = 
   PopupMenu[
    Dynamic[pass2Fun1], {1 -> "choice 1", 2 -> "choice 2", 
     3 -> "choice 3"}, ContinuousAction -> True]; 
  CreateDialog[{pup}];)

ff[];

As far as I can tell the two remain in sync if the kernel variable is set or the menu item selected.

Does this meet the criteria for the OP?

$\endgroup$
1
  • $\begingroup$ Yes it does, Thanks very much! $\endgroup$ Jul 24, 2012 at 18:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.