圆形/角度滑块

Sim*_*mon 5 wolfram-mathematica

一个最近的SO问题,让我想起了一些代码,我试着写了一段时间回来.目的是创建一个CircularSlider[]可用于动态对象中类角度变量的对象.

我的解决方案框架(如下所示)来自高级操作功能教程中的ValueThumbSlider[]定义.主要区别在于滑块的值和位置是相同的,而在我的它们不是 - 这会导致问题.ValueThumbSlider[]LocatorPlane[]CircularSlider[]

第一个问题是移动Locator不会改变滑块值.这是通过使用在第二个参数固定的Dynamic:(x = #/Abs[Complex @@ #]) &.

这反过来会导致这样的问题:如果从外部设置slider(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]]]
Run Code Online (Sandbox Code Playgroud)

替代文字


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

WRe*_*ach 5

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

如果你不在t第一个参数中赋值,可以避免问题#2 Dynamic.

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

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
      ]
  ]
Run Code Online (Sandbox Code Playgroud)

此版本与原始版本之间唯一的实质区别在于,第一个参数Dynamic是一个没有副作用的表达.


编辑

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

DynamicModule[{x = RandomReal[{0, 50}]},
  {Experimental`AngularSlider[Dynamic@x], Dynamic@x}
]
Run Code Online (Sandbox Code Playgroud)

角度滑块