NumericStepperで奇数を表示する [Edit]

Flash 8のNumericStepperインスタンスに、つぎのような[パラメータ]設定をしてみましょう(図001)。maximum = 10、minimum = 1、stepSize = 2、value = 1。[ムービープレビュー]してNumericStepperインスタンスを操作すると、値はどのように変化するでしょう?

図001■NumericStepperの[パラメータ]設定
FF0608231_001.gif

最初の表示は、valueに設定した「1」です。上向き三角[▲]ボタンをクリックすると、stepSizeの「2」が加算されて、「3」になると予想するのが普通でしょう。ところが、値は「2」になります(図002)。そして、その後は2ずつカウントアップされて、「偶数表示」になってしまいます。

図002■値は1から2にカウントアップ
FF0608231_002.gif

[パラメータ]の設定や、あるいはスクリプトによる処理などどう試しても、「1」→「3」→「5」→「7」→「9」といったいわゆる「奇数表示」ができません[*1]。これは、NumericStepperクラス[*2]に定義されているcheckValidValue()メソッドに問題があるようです。

そこで、NumericStepper.checkValidValue()メソッドを、修正してみます。ただし、ActionScript 2.0クラス定義ファイルを直接変更することは、念のため避けました。ActionScript 1.0のFunction.prototypeによる継承[*3]を利用すれば、当該ムーピー内でのみクラスのメソッドを書替えることができます(スクリプト001)。

[注記] 以下の修正スクリプトは、一応のテストはしています。しかし、その動作を保証するものではありません利用する場合には、自己の責任にてお願いします。

スクリプト001■NumericStepper.checkValidValue()メソッドの修正
// フレームアクション
// NumericStepper.checkValidValue()メソッドの修正
import mx.controls.NumericStepper;
NumericStepper.prototype.checkValidValue = function(val:Number):Number {
  var stepS:Number = this.stepSize;
  var minVal:Number = this.minimum;
  var maxVal:Number = this.maximum;
  var initDiv:Number = (val-minVal)/this.stepSize+minVal;
  var roundD:Number = Math.floor(initDiv-minVal)+minVal;
  if (val>minVal && val<maxVal) {
    if (initDiv-roundD == 0) {
      return val;
    } else {
      var tmpV:Number = Math.floor((val-minVal)/stepS);
      var stepDownV:Number = tmpV*stepS+minVal;
      if ((val-stepDownV>=stepS/2 && maxVal>=stepDownV+stepS && minVal<=stepDownV-stepS) || (val+stepS == maxVal && maxVal-stepDownV-stepS>0.00000000000001)) {
        stepDownV += stepS;
      }
      return stepDownV;
    }
  } else {
    // [追記] 2007.03.20 数値評価したvalの値がNaNの場合
     // trace([val, maxVal, minVal]);   // 確認用
     if (isNaN(val)) {
       val = 0;
     }
    // [追記]ここまで
    if (val>=maxVal) {
      return maxVal;
    } else {
      return minVal;
    }
  }
};

NumericStepper.checkValidValue()メソッドの修正スクリプト001は、たとえば以下のスクリプトでテストすることができます(スクリプト002)。NumericStepperはスクリプトで動的に作成しますので、ステージに予め配置しなくて構いません。ただし、[ライブラリ]にはNumericStepperコンポーネントを格納しておく必要があります。

スクリプト002■修正スクリプトのテスト例
// テスト例
// フレームアクション
// NumericStepperコンポーネントを[ライブラリ]に格納
// (タイムラインには何も配置しなくてよい)
// NumericStepperインスタンスを動的に配置
import mx.managers.DepthManager;
var myNumericStepper:mx.controls.NumericStepper =
this.createClassChildAtDepth(mx.controls.NumericStepper, DepthManager.kTop);
// 初期設定
myNumericStepper.move(10, 10);
myNumericStepper.minimum = 1;
myNumericStepper.maximum = 10;
myNumericStepper.stepSize = 2;
myNumericStepper.value = myNumericStepper.minimum;

[追記] 2007.03.20
NumericStepperインスタンスに値をキー入力する場合、数字以外を設定することはできません。しかし、値を削除する操作は可能です。その場合、最大値maxnumが自動的に設定されます。

空文字列("")を数値評価するとNaNに変換され、上記スクリプト001でif条件(val>=maxVal)はtrueと評価されるからです。動作結果は必ずしも問題とはいえないものの、NaNを数値比較する処理は十分考慮されたものではないでしょう。

そこで、スクリプト001にステートメントを追加し、NumericStepperの値が削除された場合は0とみなすことにしました。最小値minimumが0より大きい場合には、NumericStepperインスタンスの値は最小値に設定されます。この仕様については、他にも考え方はあるでしょう。


[*1] この問題は、FLASH-japan「NumericStepperでの奇数表示」で報告されました。

[*2] コンポーネントのクラスは、グローパルなクラスパス$(LocalData)/Classesのmxフォルダに格納されています。NumericStepperクラスは、Classes/mx/controls/NumericStepper.asに定義ファイルがあります。

[*3] ActionScript 1.0の継承の仕方につきましては、「ActionScript 2.0と1.0の継承について」をご参照ください。

その他の記事