Intelligent Technology's Technical Blog

株式会社インテリジェントテクノロジーの技術情報ブログです。

JavaFXをScalaから使う

こんにちは。櫻です。

今回はJava SE8からSwingの代わりに標準GUIライブラリになるらしいJavaFXをScalaで利用してみようと言うネタです。
お試しでJDK8で動作させましたが、JavaFX8の機能は試せていません。

以下の環境で試してみました。

JDK 1.8.0 b111
sbt 0.13.0
scala 2.10.3
scalafx 8.0.0_M2

JavaFXとScalaFX

JavaFXJavaGUIライブラリでJDK8からはSwingに代わって標準のGUIライブラリになるそうです。
JavaFXについての詳細はJava技術最前線 - Java技術最前線:ITproが参考になります。

JavaFXではGUIの構成をxmlで記述する事ができ、それを編集するScene Builderというツールも提供されています。
iOSの開発でいうxibファイルとInterfaceBuilderの様なものです。

ScalaFXはこのUI部分をScalaのDSLで記述出来る様にしようというプロジェクトです。
http://code.google.com/p/scalafx/
下記の様なコードでUIの構成を記述できます。

stage = new JFXApp.PrimaryStage {
  title = "Hello Stage"
  width = 600
  height = 450
  scene = new Scene {
    fill = Color.LIGHTGREEN
    content = new Rectangle {
      x = 25
      y = 40
      width = 100
      height = 100
      fill <== when (hover) choose Color.GREEN otherwise Color.RED
    }
  }
}

準備

sbt用のディレクトリとbuild.sbtを作ります。以下、プロジェクトディレクトリを基準にしています。

$ mkdir -p src/{main,test}/scala

build.sbtは以下の様にしておきます。

scalaVersion := "2.10.3"

libraryDependencies ++= Seq(
  "org.xerial" % "sqlite-jdbc" % "3.7.2", // sqliteを使わないなら不要
  "org.scalafx" %% "scalafx" % "8.0.0-M2"
)

この状態でsbtを実行すればよろしくやってくれます。

基本的な使い方は前述のリンク等を参考にするとして、個人的に良く使いそうなTableView、TreeView等の使い方を確認します。
(他にもWebView、TabPane、TreeTableView(JavaFX8で追加)等もありますが…)

TableView

TableViewを使う上で重要になるのは、TableViewクラスとTableColumnクラスです。
TableViewは型引数を一つ取ります。TableView[T](JavaではTableView)はT型のデータの一覧を表示するViewになります。
Tは1行の情報をもつオブジェクトの型です。
TableColumnは型引数を二つ取ります。一つはTableViewのTと同じもの、もう一つはその列で表現する型です。
TableColumn[T, U]はT型のレコードからU型のフィールドを表現する列という事になります。

たとえば

case class Record(id: Int, name: String, guest: Boolean = false)

というデータの一覧を表示するTableViewの場合、TableView[Record]というTableViewと、
TableColumn[Record, Int]、TableColumn[Record, String]、TableColumn[Record, Boolean]という3つのTableColumnを
組み立てていけば良い事になります。

object TableSample extends JFXApp {

  // 列の定義
  val idColumn = new TableColumn[Record, Int]("id") {
    cellValueFactory = f => new ObjectProperty[Int](f.value, "id", f.value.id)
    prefWidth = 80
  }
  val name = new TableColumn[Record, String]("name") {
    cellValueFactory = f => new StringProperty(f.value, "name", f.value.name)
    prefWidth = 100
  }
  val guest = new TableColumn[Record, Boolean]("guest") {
    cellValueFactory = f => new ObjectProperty[Boolean](f.value, "guest", f.value.guest)
  }

  stage = new JFXApp.PrimaryStage {
    title = "Hello ScalaFX TableView"
    scene = new Scene {
      fill = Color.LIGHTBLUE
      root = new VBox {
        hgrow = Priority.ALWAYS
        content = new TableView[Record] {
          vgrow = Priority.ALWAYS
          columns ++= Seq(idColumn, name, guest)

          items = ObservableBuffer(
            Record(1, "name1", guest = true),
            Record(2, "name2", guest = true),
            Record(3, "name3"),
            Record(4, "name4")
          )
        }
      }
    }
  }
}

これを実行するとこのようになります。

f:id:IntelligentTechnology:20131022152824p:plain

TreeView

続いてTreeViewです。
TreeViewで重要なのはTreeView[T]とTreeItem[T]の二つのクラスです。
TreeView内の一つのノードを表すのがTreeItemクラスで、Tはそのノードに対応付けるデータの型です。
例えばTreeItem[String]で

root
├─ parent1
│  ├─ child1
│  ├─ ...
│  └─ child9
└─ parent2
    ├─ child1
    ├─ ...
    └─ child9

という木を作成し表示するとこのようになります。

f:id:IntelligentTechnology:20131022154657p:plain

コードはこうなります。

object TreeSample extends JFXApp {
  val tree = new TreeView[String]() {
    vgrow = Priority.ALWAYS
    root = new TreeItem[String]("root") {
      children = Seq(nodes("parent1"), nodes("parent2"))
    }
  }

  stage = new JFXApp.PrimaryStage {
    title = "Hello ScalaFX TreeView"
    scene = new Scene {
      fill = Color.LIGHTBLUE
      root = new VBox {
        hgrow = Priority.ALWAYS
        content = tree
      }
    }
  }

  def nodes(name: String) = new TreeItem[String](name) {
    children = (1 until 10).map { i =>
      new TreeItem[String]("child" + i)
    }
  }
}

DB Viewerサンプル

TableViewやTreeViewの使い方に慣れておくと、ちょっとしたツールが簡単に作成できるようになります。
例えばJDBC経由でDBへ接続し、テーブルの一覧を取得しTreeViewで表示し、テーブルを選択するとその内容をTableViewで表示する…
の様な事が簡単にできたりします。

SQLiteのDBを開いてみた図

f:id:IntelligentTechnology:20131022155832p:plain

このサンプルで150行程度(実質100行程度?)で出来ています。
コードはこちら。
https://github.com/hatena-iti/scalafx-sample

まとめ

ScalaFXを使ってJavaFXのTableViewとTreeViewを動かしてみました。
Scalaで書いているというのもありますが、簡単にいろいろなものの可視化が出来そうです。
JavaFXでは他にもTreeTableView、WebView、グラフやチャート等も簡単に作れるようです。
使いこなせるといろいろ役に立ちそうですね。