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

时间:2011-12-07 12:50:48

标签: 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
    }
   }]
 ]

enter image description here

在上面,当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
    }
   }]
 ]

enter image description here

我的问题是:有没有办法在Mathematica中执行上述操作?我使用的是8.04。

最佳解决方案是通过动态(或整个菜单是动态的)获得菜单本身的项目列表,因此我可以告诉它在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"};
   )
 ]

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

感谢

更新

看下面的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"}]
       )
      ]
     ]
    }
   }
  ]
 ]

enter image description here

2 个答案:

答案 0 :(得分: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}]

注意当Switch发生变化时,顶部的selection会控制x的默认设置。


编辑:

根据您的请求将菜单逻辑本地化为控件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}]

a boring screenshot

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

答案 1 :(得分: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}]