ラベル Scala の投稿を表示しています。 すべての投稿を表示
ラベル Scala の投稿を表示しています。 すべての投稿を表示

2011年11月3日木曜日

ScalaでSwingレイアウト(GridBagPanel編)

scala.swingでは、レイアウトのクラスとPanelが一つのクラスになっています。
GridBagPanelはGridBagLayoutとJPanelクラスが合わさったクラスです。
GridBagPanelはレイアウトの自由度がかなり高いクラスとなっており、これを利用すれば、おおよその画面レイアウトは実装できてしまうのではないでしょうか?

主な使い方は以下の通りです。
  1. GridBagPanelの基本的な仕組み
  2. GridBagPanelクラスの基本的な利用方法
  3. GridBagPanelの色々なレイアウトオプション

ScalaでSwingレイアウト(BoxPanel編)

ScalaでSwingアプリを作っていたんですが(これまた今更ですが・・・)、Scalaに限らずSwingをやっていて、個人的にいつも困るのがフォームのレイアウトだったりします。
普段はWebプログラマ~な自分からすると、Swingのレイアウトマネージャーって、非常に使いづらい。「そんなんだから Adobe Airに・・・」なんてことが出掛ってしまうぐらい使いづらい。そんなSwingですが、Scalaを利用して実装すると少しはマシになるな~というのを実感する今日この頃なので、少しずつScalaでのSwingの利用方法を紹介できたらなんて思っています。そんでもって、まずはBoxPanelクラスを紹介しようと思います。
Scalaではパネルを設定するのにPanelクラスとレイアウトマネージャがセットになっている以下のクラスを利用するようになっています。

  1. BorderPanel
  2. BoxPanel
  3. FlowPanel
  4. GridBagPanel
  5. GridPanel
その中からBoxPanelを何故最初に紹介するかというと、フォームの右寄せ、上寄せができる数少ない(唯一?)レイアウトマネージャだからです。

  1. BoxPanelを定義し、コンポーネントを配置する方向を指定する
  2. コンポーネントの表示位置を設定する
  3. Swingクラスを利用して、隙間を挿入する

2011年8月21日日曜日

ScalaのgroupByメソッドを使ってみた

最近Scalaのコレクションクラスに「groupBy」というメソッドがあることを知り、ちょっと使ってみました。
使ってみて改めて画期的なメソッドだな~と感じたのでちょっと紹介いたします。

groupbyメソッドは引数に渡した関数の戻り値をキーにしたマップを作成するメソッドです。同じキーを返した値がマップの値になります。

例として売上げを商品毎にまとめてみます。

2011年8月7日日曜日

AntでScalaをコンパイルする

最近ScalaファイルのコンパイルをAntを利用して行うようにしたので、その方法をメモしておきます。

  1. Scalaコンパイル用タスクの設定
  2. ターゲットの作成

2011年4月17日日曜日

ScalaでClassオブジェクトを利用したリフレクション

Scalaでリフレクションというか動的なオブジェクト生成ってどうすればいいのだろうと思っていたら、

Scala: How do I dynamically instantiate an object and invoke a method using reflection?

にサンプルがあったのでメモ。

class Foo {
  def hello(name: String): String = "Hello there, %s".format(name)
}

object FooMain {

  def main(args: Array[String]) {
    val foo  = Class.forName("Foo").newInstance.asInstanceOf[{ def hello(name: String): String }]
    println(foo.hello("Walter")) // prints "Hello there, Walter"
  }
}
この方法を利用すると以前書いたAbstractFactoryのサンプルをこれで書きかえることができるので書きかえてみた。

2011年1月26日水曜日

Scala Swingでデザインパターン[Command]

また昔買った「デザインパターン入門講座」本のサンプルを実装してみました。

こちらのプログラムはCommandパターンのサンプルとして紹介されているプログラムで
  1. 「File」-「Open」からファイル選択ダイアログを開く
  2. 「File」-「Exit」からプログラムを終了する
  3. 「Red」ボタンを押下すると背景が赤になる
という3つの動作を行うだけです。

Java実例プログラムによるデザインパターン入門講座―Swingプログラムで体得する23のパターン

このサンプルを実装してみて思ったのですが、Scalaはこの方法でイベント処理を実装するのに不向きなような気がします。 サンプルで実装されているアクションの実行方法は、

  1. ボタン、メニューのコンポーネントオブジェクトにCommandオブジェクトを保持するためのインタフェースを追加する
  2. コンポーネントにCommandオブジェクトを追加する
  3. イベント発生時にイベントオブジェクトからイベント発生元のコンポーネントを取得する
  4. コンポーネントからコマンドを取り出し実行する

というものなのですが、4.のコンポーネントからコマンドを取り出すには、型キャスト(アンボクシング?)が必要になります。

ジェネリクスによる型認識を徹底的に駆使して、型付言語でありなが型を意識することなく実装していくことを意識して設計されているScalaなのに、型キャストをしなければいけないのはいかがなものかと思ってしまうわけです。

ScalaではScalaなりのアクションの実装方法があるような気がするんですが、それがなんだかは全く検討がつきません。

そのうち気付くかな?でも、そこまで Scala + Swing を追求していこうとも思っていなんですが・・・・。

型キャストはasInstanceOf[T]というメソッドで行うことができます。

実装例は下記のとおりになります。
reactions += {
  case ButtonClicked(a) => a.asInstanceOf[CommandHolder].command.execute
}
本サンプルのソースはこちら

2011年1月20日木曜日

Swingでデザインパターン[Bridge]

「デザインパターン入門講座」本から「Bridge」パターンのサンプルをScalaで実装してみました。 今回は一つのデータを利用して、一般顧客用とエグゼクティブ顧客用の2種類のビューを生成するというものです。 コンポーネント追加用のメソッドを持つ抽象クラスをつくり、それを実装するクラスに委譲の形でコンポーネントを持たせています。

そして、コンポーネントもインタフェースをかませることで抽象度を高くしています。

Java実例プログラムによるデザインパターン入門講座―Swingプログラムで体得する23のパターン

個人的には、コンポーネント追加用の抽象クラスがBorderPanelを継承しているところがちょっと気になりました。 デスクトップアプリ(Swing)以外の方法で表示したくなったときにどうするのかな?と。「そこは、継承より委譲だろ」と思ってしまいました。Swing、デザパタに詳しい人とかはひょっとしたらもっと大きな問題に気付けたりするのかもしれないですが、自分ではこれが精一杯。

今回はまったのがずばりscala.swingパッケージにJTreeのラッパークラスがない!!ということでした。

なんで、JTreeのラッパーだけないんでしょう?実装漏れ?JTreeクラスに何か欠陥があるのか?「こんなコンポーネントいらね~よ」と実装者が思ったのでしょうか?まあ、考えてもしょうがないのですが・・・・。

かなり調べるのに時間がかかってしまったのですが、scala.swing.Componentクラスの中にコンポーネントを委譲させるように実装すれば言いということがわかりました。
実装例は下記の通り
viewportView = new Component {
    override lazy val peer = new JTree(root)
  }

あまりいいサンプルじゃないので、もう一つ

class Tree extends Component {
  override lazy val peer = new JTree(root)
}

遅延評価変数になっているところがミソ?なのかな・・・。

Scala Swing 独特のイベントリスナの実装も割と簡単にできるのですが、それはまた別の機会にということで(知りたい人はコメントとかくれるとありがたいです)。

あと今回、Javaのリフレクション機能を利用して文字列から動的にクラスを生成する方法を色々調べたのですが、結局わからずじまいとなってしまいました。Scalaという言語の特性上、基本的にやらないほうがいい処理なんでしょうか?
ちなみに、コップ本でもプログラム内で生成処理を分岐させて別のクラスの実装を返す方法しか紹介されていませんでした(27章)。

本サンプルのソースとサンプル内で利用したデータファイルはこちら

2011年1月18日火曜日

Scala Swingでデザインパターン[Abstract Factory]

「デザインパターン入門講座」本のAbstract FactoryパターンのサンプルをScalaで実装してみました。 こちらは、左のラジオボタンで選択した庭園の種類に応じて、ボタンを押下したときに右上のパネルに表示される文字列が異なってくるというものです。
ラジオボタンに対応する庭園クラスがあるのですが、それぞれの庭園クラスの親クラスを実装し、イベントアクション内では親クラスを操作するという形になっています。Factoryクラスは直感的だから、そんなに説明も必要ないとは思いますが・・・・

Java実例プログラムによるデザインパターン入門講座―Swingプログラムで体得する23のパターン このサンプルは、特に困ることもなく実装できました。 強いて言うと、GridBagPanelクラスの中で利用するConstraintsオブジェクトをどうやって生成するのだろう?というところで、少しつまづいたぐらいでした。 結局GridBagPanelクラスの中のpairConstraintsメソッドから生成する方法ぐらいしかわかりませんでした。 まあ、こちらのメソッドの利用方法はAPIドキュメントをみればすぐわかると思うので、あえてここでは何も書きません。
本サンプルのソースはこちら

2011年1月14日金曜日

setterと「_」(アンダースコア)の不思議

ScalaでSwingのプログラムを組もうとして、apiのドキュメントを見ていたら、ちょいちょい「_=」で終わるメソッド名が目についた。

気になって、調べて見たら

Getters and Setters in Scala | The Personal Blog of Dustin Martin

を発見。

一番下のほうに

First, the method name is “age_=”. The underscore is a special character in Scala
and in this case, allows for a space in the method name which essentially makes
the name “age =”.

とあるんだけど訳すと

最初にメソッド名は "age_="となる。アンダースコアはScalaでは特別な文字で、この場合メソッド名に空白を許可し、メソッド名を実質的に "age =" とする

という意味になる。なんとなくこの文章読んで思ったのが
「文字列と"="の間に複数の空白が入ると実はエラーになるのでは」
と思って試してみた。

class SimpleTest {
   var _simpleTest = ""
   def test_=(strTest: String) = {_simpleTest = strTest}
   def test = _simpleTest
}

これを下記のように実行すると

val hoge = new SimpleTest
hoge.test = "Hello" // OK
hoge.test     = "Hello" //OK

という感じでどっちも問題なかった。

表記の仕方からするとエラーになった方が自然なような気がするんだけど、まあ、エラーにされると不便だからいいか。
でも不思議~~。

2011年1月2日日曜日

Scala Swingでデザインパターン[Simple Factory]

ScalaのGUIプログラムの実行方法がわかったところで、今度はもうちょっと複雑なプログラムを組んでみようかな~ということで、昔買ったデザインパターンをSwing or awt なGUIのサンプルを用いて解説している本のサンプルを実装してみました。
こちらのプログラムは画面上部のテキストボックスに名前を入力したら、名前を姓(Last Name)と名(First Name)に分割してそれぞれのテキストボックスに表示するという簡単なプログラムです。
1. 名前を半角空白区切りにすると前が名で後ろが姓
2. 名前をカンマ区切りにすると前が姓で後ろが名

というような分割ルールになっています。

結構簡単なプログラムのはずなんですが、思いのほかはまってしまいました。
はまりポイントは下記の通り

2010年12月29日水曜日

はじめてのScala Swing ~SimpleGUIApplicationにはまる~

最近Scalaを学ぼうと思って、コップ本を購入しました。
とりあえず何か楽しそうなところからということで、ScalaのGUIプログラミングから始めました。
import scala.swing._

object FirstSwingApp extends SimpleGUIApplication {
 def top = new MainFrame {
  title = "First Swing App"
  contents = new Button {
   text = "Click me"
  }
 }
}

これを
C:\Study\Scala>scala FirstSwingApp.scala

として実行しようとしたら、何もおきずにプログラムが終了してしまった。
最初に何かを間違えてしまったのかと色々調べても一向に解決策が見つからない・・・。

結局
C:\Study\Scala>scalac FirstSwingApp.scala
C:\Study\Scala>scala FirstSwingApp

で無事実行することができた。
scalacでコンパイルしたプログラムはscalaコマンドで実行できるらしい。