圆形/角度滑块

时间:2010-12-12 09:11:36

标签: wolfram-mathematica

A recent SO question让我想起了我曾经写过的一些代码。目的是创建一个CircularSlider[]对象,可用于动态对象中的类角度变量。

我的解决方案框架(如下)来自Advanced Manipulate Functionality教程中定义的ValueThumbSlider[]。主要区别在于ValueThumbSlider[]滑块的值和LocatorPlane[]的位置是相同的,而在CircularSlider[]中它们不是 - 这会导致问题。< / p>

第一个问题是移动Locator不会改变滑块值。通过使用Dynamic(x = #/Abs[Complex @@ #]) &中的第二个参数来解决此问题。

这又会导致如果您从外部设置滑块(t)的外部值,它将立即恢复到之前的值。通过保留旧值(t0)并与t进行比较来解决此问题。如果它们不匹配,则假设t已更改,因此Locator位置x将更新为新位置。

CircularSlider[t_] := CircularSlider[t, {0, 1}];
CircularSlider[Dynamic[t_], {min_, max_}] /; max > min := 
 With[{d = (max - min)/(2. Pi)},
  DynamicModule[{td = t/d, x, t0}, x = {Cos[td], Sin[td]};
   LocatorPane[
    Dynamic[If[!NumberQ[t], t = min; x = {Cos[td], Sin[td]}];
     If[t != t0, t0 = t; x = {Cos[td], Sin[td]}];
     t = Mod[Arg[Complex @@ x] d, max, min]; t0 = t;
     x, (x = #/Abs[Complex @@ #]) &],
    Graphics[{AbsoluteThickness[1.5], Circle[], 
      Dynamic[{Text[NumberForm[t, {3, 2}], {0, 0}]}]}],
    ImageSize -> Small]]]

alt text


所以我的问题是:有人可以用上面的kludges来完成这项工作吗?

1 个答案:

答案 0 :(得分:5)

对于问题#1,我不会考虑将Dynamic的第二个参数用作kludge - 这就是第二个参数的用途。因此,我没有替代解决方案。

如果您不在t的第一个参数中分配Dynamic,则可以避免问题#2。

考虑到这一点,这是另一个实现:

CircularSlider2[Dynamic[t_], r:{min_, max_}:{0, 1}] :=
  DynamicModule[{scale, toXY, fromXY},
      scale = (max - min) / (2. Pi);
      toXY[a_?NumberQ] := Through@{Cos, Sin}[a / scale];
      toXY[a_] := {1, 0};
      fromXY[{x_, y_}] := Mod[Arg[x + I y] scale, max, min];
      LocatorPane[
        Dynamic[toXY[t], (t = fromXY[#])&],
        Graphics[{
            AbsoluteThickness[1.5], Circle[],
            Dynamic[{Text[NumberForm[t, {3,2}], {0, 0}]}]
          }],
        ImageSize -> Small
      ]
  ]

此版本与原始版本之间唯一的重要区别是Dynamic的第一个参数是一个没有副作用的表达。


修改

我在Mathematica 8中偶然发现了这个未记录的实验性功能:

DynamicModule[{x = RandomReal[{0, 50}]},
  {Experimental`AngularSlider[Dynamic@x], Dynamic@x}
]

angular slider