如何定义部分 Manipulate 控制变量定义以减少代码重复 [英] How to define part of a Manipulate control variable definition to reduce code duplication

查看:23
本文介绍了如何定义部分 Manipulate 控制变量定义以减少代码重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这和这个问题有点关系

在 Mathematica 中将控件定义为变量

但是上面的问题没有回答我的问题,因为它谈到了完整的控制定义.(我也尝试了那里展示的一些技巧,但它们对我的问题不起作用).

But the above question did not answer my problem, as it talks about the full control definition. (I also tried some of the tricks shown there, but they do not work for my problem).

我现在只询问部分控件的定义.(用这种论坛格式也很难跟进一个老问题.因为使用很小的评论区,很难提出和展示更像是在问一个空间更大的新问题时,可以粘贴代码和图片).

I am now asking about definition for only part of the control. (It is also very hard to follow up on an old question using this forum format. Because using the tiny comment area, it hard to ask and show more like when asking a new question where the space is larger, and one can paste code and images).

我所做的所有尝试都不起作用.我会从简单的例子开始说明问题.

All the tries I have made do not work. I'll start by simple example to explain the problem.

假设有人想写

Clear["Global`*"];

Manipulate[Plot[f*g, {x, -1, 1}],
 Grid[{
   {Style["f(x)="], 
    PopupMenu[Dynamic[f], {x, x^2, x^3}, ImageSize -> Tiny]},{Style["g(x)="], 
    PopupMenu[Dynamic[g], {x, x^2, x^3}, ImageSize -> Tiny]}
   }]
 ]

您可以看到每个控件定义中都有大量的代码重复.(像 ImageSize、Spacings-> 和许多其他装饰设置,会为每个控件一遍又一遍地重复.

you can see there is allot of code duplication in each control definition. (things like ImageSize, Spacings-> and many other decoration settings, are repeated over and over for each control.

如果我能写出类似的东西,那该多好

What will be great, if I can write something like

Manipulate[Plot[f*g, {x, -1, 1}],
 Grid[{
   {Style["f(x)="], PopupMenu[Dynamic[f], Evaluate@Sequence@v]},
   {Style["g(x)="], PopupMenu[Dynamic[g], Evaluate@Sequence@v]}
   }],

 Initialization :>
  (
   v = {{x, x^2, x^3}, ImageSize -> Tiny}
   )
 ]

但这行不通.我沿着上述路线尝试了许多其他事情,但没有任何效果.喜欢

But this does not work. I tries many other things along the above line, and nothing works. Like

{Style["f(x)="], PopupMenu[Dynamic[f], v]},

{Style["f(x)="], PopupMenu[Dynamic[f], Evaluate@v]}

Manipulate[Plot[f*g, {x, -1, 1}],

 {{v, {{x, x^2, x^3}, ImageSize -> Tiny}}, None},
 Grid[{
   {Style["f(x)="], PopupMenu[Dynamic[f], Evaluate@v]},
   {Style["g(x)="], PopupMenu[Dynamic[g], v]}
   }]
 ]

无法让它工作.

但这里是游戏规则:这将是一个演示,因此,代码必须以 Manipulate 开头.在 Manipulate 之外不能有模块.另外,不能使用 Hold 和它的朋友.但可以使用未评估.

But here are the rules of the game: This will be for a demo, hence, code must start with Manipulate. Can't have Module outside Manipulate. Also, can not use Hold and its friends. But can use Unevaluated.

我希望这里的专家可能有一个技巧来做到这一点.如果可能的话,将减少代码大小,因为我拥有的许多控件都包含许多与上述相同的选项",并且能够执行上述操作将使代码更易于阅读和管理.

I was hoping the experts here might have a trick to do this. The will reduce the code size if it is possible to do, as many of the control I have, contain many 'options' like the above that are the same, and being able to do the above will make the code easier to read and manage.

谢谢,

ps.我所要求的,有点类似于对 Plot 选项所做的事情,可以使用 SetOptions 来设置一些常见的默认选项,这样他们就不必每次都为每个 Plot 命令复制它们.但在这种情况下没有这样的事情.

ps. What I am asking for, is sort of similar to what one does for say Plot options, where one can use SetOptions to set some common default options so they do not have to duplicate them for each Plot command each time. But there is no such thing in this case.

更新

使用下面列昂尼德所示的方法(宏技巧),我想用它来帮助我定义控件数量,所有控件都使用一个通用设置.这是我试过的:

Using the method shown by Leonid below, (the Macro trick), I wanted to use it to help me define number of controls, all using one common setting. This is what I tried:

Manipulate[{x, y},

 Evaluate@With[
   {
    control1 = Function[{var, initialValue, str, from, to, incr},
      {
       {{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}
       }
      ,
      HoldAll
      ]
    },

   {
      First@control1[x, 0, "x=", 0, 1, .1],
      First@control1[y, 0, "y=", 0, 2, .1],
      First@control1[z, 0, "z=", 0, 10, .1]
    }, 

   ]
 ]

问题只是整个事情的一个额外 {},否则它会起作用.会继续努力解决这个问题.但是越来越近了.尝试过 Sequence[] 和 Flatten[..,1] 等,但还不能做到.多煮点咖啡应该会有帮助.

The problem is just an extra {} around the whole thing, else it will work. Will keep trying to solve this. But getting close. Tried Sequence[], and Flatten[..,1] and such, but can not do it yet. Making more coffee, should help.

更新 2

下面是一个使用 Simon 方法来帮助定义跨多个控件的通用定义的示例.这样,就可以使用它来减少一组单独控件上的公共选项的代码重复

This is below an example using Simon method to use to help define common definition across more than one control. This way, one can use it to reduce code duplication for common options on set of separate controls

注意,必须使用 Control[] 来控制它.

Notice, had to use Control[] to get it to control.

Manipulate[{x, y, z},

 Dynamic[Grid[{
    {control1[x, 0, "x=", 0, 1, .1]},
    {control1[y, 0, "y=", 0, 2, .1]},
    {control1[z, 0, "z=", 0, 10, .1]}
    }]],

 {{control1, 
   Function[{var, initialValue, str, from, to, incr}, 
    Control[{{var, initialValue, str}, from, to, incr, 
      ImageSize -> Tiny}], HoldFirst]}, None}

 ]

更新 3

并且让 Leonid 方法也适用于多个控件.诀窍是使用Control[].不能使用普通的旧 {{x,0,"x"},...} .

And got Leonid method to work also on more than one control. The trick is to use Control[]. Can't use plain old {{x,0,"x"},...} .

这是:

Manipulate[{x, y, z},

 Evaluate@With[
   {
    control1 = Function[{var, initialValue, str, from, to, incr},
      Control[{{var, initialValue, str}, from, to, incr, 
        ImageSize -> Tiny}]
      , HoldAll
      ]
    },

   Grid[{
     {control1[x, 0, "x=", 0, 1, .1]},
     {control1[y, 0, "y=", 0, 2, .1]},
     {control1[z, 0, "z=", 0, 10, .1]}
     }]

   ]
 ]

我将尝试将其中一种方法集成到我的主要演示中(到目前为止,仅有 600 多行代码仅用于控件布局,并且每分钟都在增加,希望这些方法可以将其缩小很多)

I'll try to integrate one of these methods into my main demo (has over 600 lines of code just for the control layout so far and growing by the minute, hopefully these methods will shrink this by quite a bit)

更新 9/26/11.晚上 7 点

我想我通过使用宏"来定义包含许多常见样板代码的控件来发布代码保存的鸟瞰"视图.这是之前和之后的屏幕截图.

I thought I post a 'birds eye' view of the code saving by using 'macros' to define controls which contains many common boiler-plate code. Here is a screen shot of before and after.

再次感谢所有的回答和帮助.

Thanks again for all the answer and help.

推荐答案

这个怎么样

Manipulate[Plot[f*g, {x, -1, 1}],
 Evaluate@
  With[{styleAndpopup = 
      Function[{st, fun}, 
         {
           Style[st], 
           PopupMenu[Dynamic[fun], {x, x^2, x^3}, ImageSize -> Tiny]
         }, 
         HoldAll]},
    Grid[{styleAndpopup["f(x)=", f], styleAndpopup["g(x)=", g]}]]]

这实际上是代码生成工作的一个小例子,因为如果您查看结果 ManipulateFullForm,您将看到与您相同的表达式最初开始于.styleAndpopup 实际上不是这里的函数,而是一个宏,使用 With 在本地定义.

This is actually a tiny example of the code-generation at work, since if you look at the FullForm of the resulting Manipulate, you will see the same expression you originally started with. The styleAndpopup is actually not a function here, but a macro, locally defined using With.

编辑

根据 OP 的要求 - 推广到许多控件.最简单的解决方法是插入 Sequence@@... 作为 Sequence @@ {First@control1[....但是,也可以删除一些无关的内容:

Per request of the OP - generalizing to many controls. The easiest fix is to insert Sequence@@... as Sequence @@ {First@control1[.... However, there is some extraneous stuff that can be removed as well:

Manipulate[{x, y}, 
 Evaluate@With[{control1 = 
     Function[{var, initialValue, str, from, to, incr}, 
       Unevaluated@{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}, 
       HoldAll]}, 
   Sequence @@ {
     control1[x, 0, "x=", 0, 1, .1], 
     control1[y, 0, "y=", 0, 2, .1], 
     control1[z, 0, "z=", 0, 10, .1]}]]

这篇关于如何定义部分 Manipulate 控制变量定义以减少代码重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆