如何在Mathematica中制作选择性下拉菜单?

Nas*_*ser 5 wolfram-mathematica

我在Manipulate界面上的空间不足.所以,我希望看看我是否可以重载PopupMenu以满足多个目的.

这是问题所在:

我有一个PopupMenu,用于从中选择一个条目.但是根据我在其他地方做出的另一个选择,菜单中的某些条目将不再有意义进行选择.

所以,我想知道,如果我可以根据动态设置在PopupMenu'selectable'中创建一些条目?(可能被禁用,或者变灰,或者什么是最好的,整个列表本身是动态的,即整个popUp菜单是动态的,所以我可以根据另一个动态的值选择不同的菜单.但我不认为这是可能的)

目前,可以根据动态设置启用或禁用WHOLE PopupMenu.但我想在Popupmenu内的入门级做到这一点.

这是一个例子来说明:

Manipulate[selection,
 Grid[{
   {"x", SetterBar[Dynamic[x], {1, 2}]},
   {"selection", PopupMenu[Dynamic[selection],
     {
      "NONE", "SOR", "SSOR"
      }, Enabled -> Dynamic[x == 1]], SpanFromLeft
    }
   }]
 ]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在上面,当X = 1时,启用整个菜单.

但我想要的是,如果X = 1,则只能选择"NONE"(或列表只显示"NONE"),当X = 2时,则只能选择"SOR"和"SSOR" "(或列表只显示这两个选项).

即如果x = 2,系统将不会选择"SOR".尝试选择它将不会导致任何更改,菜单将保持其先前的设置而不会更改.

再一次,我知道我可以把东西分成2个popuMenus,并根据下面的X设置控制每个,但是我没有更多空间来添加更多菜单:

Manipulate[If[x == 1, selectionA, selectionB],
 Grid[{
   {"x", SetterBar[Dynamic[x], {1, 2}]},
   {"selection", PopupMenu[Dynamic[selectionA],
     {
      "NONE"
      }, Enabled -> Dynamic[x == 1]], SpanFromLeft
    },
   {"selection", PopupMenu[Dynamic[selectionB],
     {
      "SOR", "SSOR"
      }, Enabled -> Dynamic[x == 2]], SpanFromLeft
    }
   }]
 ]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我的问题是:有没有办法在Mathematica中完成上述操作?我使用的是8.04.

最好的解决方案是通过Dynamic(或整个菜单是动态的)获得菜单本身的项目列表,所以我可以告诉它在X = 1时使用listA或在X = 2时使用listB等.但是我不知道该怎么做,也不知道是否有可能.

PS.这是我目前尝试解决的问题

Manipulate[selection,

 Grid[{
   {"x", SetterBar[Dynamic[x], {1, 2}]},
   {"selection", PopupMenu[Dynamic[selection],
     {
      Dynamic[If[x == 1, listA, listB]]
      }
     ]
    }
   }
  ],
 Initialization :>
  (
   listA = {"A", "B"};
   listB = {"C", "D"};
   )
 ]
Run Code Online (Sandbox Code Playgroud)

但它还不太好用.会坚持下去......

谢谢

更新:

看下面的Simon解决方案给了我更多的启发,所以这就是我到目前为止所拥有的:

Manipulate[selection,

 Grid[{
   {"x", SetterBar[Dynamic[x], {1, 2}]},
   {"selection",

    Dynamic[If[x == 1,
      (
       selection = "A";
       PopupMenu[Dynamic[selection], {"A", "B"}]
       ),
      (
       selection = "C";
       PopupMenu[Dynamic[selection], {"C", "D"}]
       )
      ]
     ]
    }
   }
  ]
 ]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Sim*_*mon 6

这是你要找的东西吗?

Manipulate[
 Switch[x,
        1, If[selection =!= None, selection = None],
        2, If[selection === None, selection = "SOR"]];
 selection,
 {x, {1, 2}, ControlType -> SetterBar},
 {{selection, None}, Switch[x, 1, {None}, 2, {"SOR", "SSOR"}, _, {"huh"}], 
  ControlType -> PopupMenu}]
Run Code Online (Sandbox Code Playgroud)

请注意,Switch以控制为默认顶部selectionx被改变.


编辑:

根据您的要求将菜单逻辑本地化到控件Grid并窃取Heike的默认机制,这是一个新版本:

Manipulate[selection,
 Grid[With[{menu = {{None}, {"A", "B"}, {"emu", "num"}}},
   {{"Which menu?", SetterBar[Dynamic[x], Range[Length[menu]]]},
    {"Menu selection:", Dynamic[
      If[MemberQ[menu[[x]], selection], selection = menu[[x, 1]]];
      PopupMenu[Dynamic[selection], menu[[x]]]]}}]],
 {{selection, None}, None}, {{x, 1}, None}]
Run Code Online (Sandbox Code Playgroud)

一个无聊的截图

请注意,menu列表不需要使用With语句进行本地化- 可以在代码中的其他位置进行设置.


Hei*_*ike 5

这个解决方案类似于Simon的答案,但它没有明确使用列表的数量,所以它应该适用于任意数量的列表

choices = {{"a", "b", "c"}, {None}, {"e", "f"}};

Manipulate[
 If[Not[MemberQ[x, selection]], selection = x[[1]]];
 selection,
 {{x, choices[[1]]}, MapIndexed[# -> #2[[1]] &, choices], SetterBar}, 
 {selection, x, ControlType -> PopupMenu}]
Run Code Online (Sandbox Code Playgroud)