SimpleButtonクラスのenabledプロパティについて

懲りずにAS3.0でハマったことをメモ。

AS3.0にはSimpleButtonという便利なクラスがあります。これはDisplayObjectContainerクラスを継承していないので、自身に子オブジェクトをaddChild()することはできないのですが、upState、overState、downStateという3つのプロパティに、それぞれDisplayObjectを設定することができます。これはそれぞれマウスの「ロールアウト」、「ロールオーバー」、「ロールダウン(クリック)」の状態に相当します。

またhitTestStateというプロパティにも同様にDispalyObjectを設定することが可能ですが、これはビジュアル的には表示されずに、ボタンの当たり判定領域を指定するためのプロパティです。

これらのプロパティへ格納するオブジェクトはいつでも変更することができるので、いわゆるトグルボタンなども簡単に作成することができます。またupState、overState、downStateに割当てられたそれぞれのオブジェクトは、単にビジュアル表示だけのためではなく、SimpleButtonクラスのプロパティとして設定しておけば、そのオブジェクトのメソッドも使用することができます。

僕は最初SimpleButtonという名前から「これは簡易的なボタンを作成するときに使うクラスなのかな」と思ったのですが、それは間違っていたようで、相当重宝しています。

さて、そんな優秀なSimpleButtonですが、ちょっと「はてな?」なプロパティがあります。それはenabledというプロパティで、このプロパティをfalseに設定すると、ボタンはマウスアクションに関わらず、常にupState状態を表示するようになります。またロールオーバー時のマウスカーソルの形状も、ハンドカーソルからデフォルトの矢印カーソル(?)に変わります。

当然これは「ボタンを無効にする」=「クリックできないようにする」ためのプロパティだと思いますよね。ドキュメントにもそう書かれていますし。

ところがそうではなくて、enabled = false にしてもこのオジェブクトに登録されているイベントはディスパッチされてしまうのです。つまり、このプロパティをfalseにするのは、overStateとdownStateの設定をupStateと同じにして、useHandCursorをfalseに設定するのと何ら変わらないって事?表示上はクリックできないような感じですが、マウスをクリックすると当然ボタンに登録されているイベントは発生します。んがー、何で?

Adobeの上条さんのエントリにもさらりと「enabled を false に設定すると、実際マウスを操作しても見た目上は反応しなくなります。ただし、イベントはディスパッチされるようです。」と書かれているので、最初からそういう仕様として設計されたのでしょうが、ちょっと存在意義がハテナな感じです。少なくともAS2.0のときは、(MovieClipの?)enabledをfalseに設定するとイベントも発生しなくなったと思うのですが。

で、僕はボタンのイベントハンドラのほうを

function clickHandler(event:MouseEvent):void {
  if (event.currentTarget.enabled) trace("click");
}

みたいな感じにして対応したのですが、登録するイベンハンドラの数が多い場合はカスタムボタンクラスとか作成したほうが良さそうですねー

【2007.10.17追記】
SimpleButtonクラスのスーパークラスであるInteractiveObjectクラスにmouseEnabledというプロパティがありました。SimpleButtonのボタンとしての機能は無効化したい場合は、このプロパティをfalseにしてやるというのがスマートな方法っぽいですね。