イベントの扱い
SimpleSwingApplication を使用した簡単なイベント処理の例です。Frame にマウスクリック回数を表示する Label を配置します。
import swing._ object Counter extends SimpleSwingApplication { val label = new Label { text = "0" listenTo(mouse.clicks) reactions += { case e: event.MouseClicked => text = (Integer.parseInt(text) +1).toString } } def top = new MainFrame { title = "Counter" contents = label } }
上記コードの実行結果は以下のようになります。
マウスクリックに応じて Label のカウンターがカウントアップします。
リスンするイベントを以下で登録しています。
listenTo(mouse.clicks)
listenTo は SwingApplication extends Reactor の Reactorトレイトで定義されています。
trait Reactor { val reactions: Reactions = new Reactions.Impl def listenTo(ps: Publisher*) = for (p <- ps) p.subscribe(reactions) ・・
listenTo メソッドに Publisher としてイベントの発生元となるオブジェクトを登録します。listenTo メソッドでは、イベントの発生元となる Publisher と、イベントの結果の動作をサブスクライブとして関連付けています。
上記で登録している Publisher は、Component クラスにて以下のように定義されている mouse.clicks オブジェクトです。
object mouse { val clicks: Publisher = new Publisher { peer.addMouseListener(new MouseListener { def mouseClicked(e: java.awt.event.MouseEvent) { publish(new MouseClicked(e)) } ・・・ }) } }
イベントの結果としての動作は以下のコードで登録しています。
reactions += { case e: event.MouseClicked => text = (Integer.parseInt(text) +1).toStrin }
mouse.clicks にて発生する event.MouseClicked イベント時の動作を reactions に追加しています。
コンポーネントのイベント処理
次に摂氏/華氏変換の例を見てみます。
import swing._ object Converter extends SimpleSwingApplication { def newField = new TextField { columns = 5 } val celsius = newField val fahrenheit = newField def top = new MainFrame { title = "摂氏(℃)/華氏(F)" contents = new FlowPanel( celsius, new Label("℃ = "), fahrenheit, new Label("F")) } listenTo(celsius, fahrenheit) reactions += { case event.EditDone(`celsius`) => val c = Integer.parseInt(celsius.text) fahrenheit.text = (c * 9 / 5 + 32).toString case event.EditDone(`fahrenheit`) => val f = Integer.parseInt(fahrenheit.text) celsius.text = ((f - 32) * 5 / 9).toString } }
最初の例と同様に listenTo にテキストフィールドを Publisher として登録しています。
listenTo(celsius, fahrenheit)
イベントに対する反応は以下のようにテキストフィールドの発行する EditDone に応答する摂氏/華氏変換を行いテキストフィールドに設定しています。
reactions += { case event.EditDone(`celsius`) => val c = Integer.parseInt(celsius.text) fahrenheit.text = (c * 9 / 5 + 32).toString case event.EditDone(`fahrenheit`) => val f = Integer.parseInt(fahrenheit.text) celsius.text = ((f - 32) * 5 / 9).toString
EditDone は以下のようなケースクラスです。
case class EditDone(override val source: TextField) extends ValueChanged(source)