S-JIS[2011-04-04] 変更履歴

Scala イベント(Swing)

ScalaSwingのイベント取得方法のメモ。


概要

JavaのSwingでは、イベントを受け取る為のリスナーを用意し、コンポーネントにリスナーを登録する。
すると、コンポーネントでイベントが発生した時にそのリスナーのメソッドが呼ばれる。
(イベント毎に呼ばれるメソッドが異なる)

ScalaのSwingでは、コンポーネントのreactionsに登録した関数でイベントを受け取る。
その関数の中でイベントのパターンマッチを行ってイベント毎の処理を行う。


ボタンクリックイベント

ボタンが押された時のイベントを受け取る例。

import scala.swing._
import scala.swing.event.ButtonClicked
object EventSample extends SimpleSwingApplication {
  override def top = new MainFrame {
    title = "サンプル"
    contents = new FlowPanel {
      contents += new Button("ボタン") {
        reactions += {
          case ButtonClicked(source) => println(source)
        }
      }
    }
  }
}

scala.swing.Buttonでは、ボタンが押下されるとButtonClickedが送られてくる。

ボタン押下時の処理はActionを使う方法もある


マウスおよびキーイベント

scala.swing.Component(LabelやButton等の親クラス)では、マウス(移動・クリック・ホイール)とキー入力のイベントを受け取れるようになっている。

import scala.swing._
import scala.swing.event.MouseClicked
      new Label("ラベル") {
        listenTo(this.mouse.clicks)
        reactions += {
          case MouseClicked(source, point, modifiers, clicks, triggersPopup) => println(modifiers, clicks)
        }
      }

listenToメソッドで、どのイベントを受け取るのか決めるのがポイント。

オブジェクト イベント 説明 イベントの値
mouse.clicks MouseClicked マウスがクリックされた。 source Component コンポーネント
point Point 座標
modifiers Key.Modifiers 同時に押されていたキーの種類
clicks Int クリック回数
triggersPopup Boolean  
MousePressed マウスボタンが押された。     MouseClickedと同じ
MouseReleased マウスボタンが離された。     MouseClickedと同じ
mouse.moves MouseEntered マウスカーソルがコンポーネント上に入ってきた。 source Component コンポーネント
point Point 座標
modifiers Key.Modifiers 同時に押されていたキーの種類
MouseExited マウスカーソルがコンポーネント上から出た。     MouseEnteredと同じ
mouse.wheel MouseWheelMoved マウスのホイールを回転された。 source Component コンポーネント
point Point 座標
modifiers Key.Modifiers 同時に押されていたキーの種類
rotation Int  
keys KeyTyped キー(文字)が入力された。 source Component コンポーネント
char Char 文字
modifiers Key.Modifiers 同時に押されていたキーの種類
location Key.Location  
KeyPressed キーが押された。     KeyTypedと同じ
KeyReleased キーが離された。     KeyTypedと同じ

例えばlistenTo(mouse.moves)を実行すると、MouseEnteredとMouseExitedが送られてくるようになる。
listenToは可変長引数なので、listenTo(mouse.clicks, mouse.moves)の様に複数指定することが出来る。


複数のコンポーネントで同じイベント処理を行う場合、トレイトにしてミックスインするのが便利。

trait MyReaction {
  self: Component =>

  listenTo(this.mouse.clicks)
  reactions += {
    case MouseClicked(source, point, modifiers, clicks, triggersPopup) => println(source, modifiers, clicks)
  }
}
    contents = new FlowPanel {
      contents += new Label("ラベル1") with MyReaction
      contents += new Label("ラベル2") with MyReaction
      contents += new Label("ラベル3") with MyReaction
    }

他コンポーネントでイベントを受け取る

イベントは自分のコンポーネント以外でも受け取れる。

import scala.swing._
import scala.swing.event._
object EventFrameSample extends SimpleSwingApplication {
  override def top = new MainFrame {
    title = "サンプル"

    val label1 = new Label("ラベル1")

    contents = new FlowPanel {
      contents += label1
      contents += new Label("ラベル2") {
        listenTo(label1.mouse.clicks)
        reactions += {
          case MouseClicked(source, point, modifiers, clicks, triggersPopup) => println("label2", source, modifiers, clicks)
        }
      }
    }

    listenTo(label1.mouse.clicks)
    reactions += {
      case MouseClicked(source, point, modifiers, clicks, triggersPopup) => println("frame", source, modifiers, clicks)
    }
  }
}

フレーム(MainFrame)のコンストラクター内でlistenToとreactionsの指定を行えば、フレームでイベントを受け取ることが出来る。
ラベル2の中でラベル1をlistenToしてやれば、ラベル2でも(同じイベントを)受け取れる。


Scala Swingへ戻る / Scala目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま