Layout in JavaFX 1.2 Part 2

レイアウトシリーズの第2弾となる今回は Tile がテーマです。

前回の Flow を書き終えて、Tile と戯れること早三日...
Flow と違って なかなか言うことを聞いてくれず、悪戦苦闘...

と言うことで...
まずは Tile の特徴を簡単に...

Tile は 全 Node の基点(通常 Node の左上端の位置)が等間隔になるようにレイアウトされます。
デフォルトでは、基点間の距離は 一番大きい Node に合わせて設定されますが、tileWidth, tileHeight で任意の値も指定できます。
また、縦に並べる Node の数 と 横に並べる Node の数 は、rows, columns でそれぞれ指定できます。

と文章で書いてもあまりイメージがわかないので、今回も直接属性を操作して レイアウトを確認できるように、前回のアプリケーションを改造してみました。
あまり、作り込む時間がなかったので、レイアウト等はイマイチですが、また時間があるときにでも直そうと思います。折角レイアウトをテーマにしているんだし...

画面は こんな感じ...





あと、以下は 今回わかったこと と ハマったこと...

1. rows, columns に bind すると com.sun.javafx.runtime.AssignToBoundException が発生

縦横の Node の数を動的に変更しようと思い、columns, rows に bind してみたら 以下のエラーが発生しました。
仕方なく、columns, rows を変更する場合は、Tile を再作成することにしました。

Unexpected exception caught in MasterTimer.timePulse():
com.sun.javafx.runtime.AssignToBoundException: Cannot assign to bound variable
        at com.sun.javafx.runtime.location.IntVariable.setAsInt(IntVariable.java:111)
        at javafx.scene.layout.Tile.set$columns(Tile.fx:127)
        at javafx.scene.layout.Tile.tileHorizontal(Tile.fx:359)
        at javafx.scene.layout.Tile.doLayout(Tile.fx:349)

2. rows, columns, width, height は複数指定しても有効なのは1つだけ

rows, colums, width, height は、どれも 縦横の Node の数を決定するために指定する属性ですが、複数同時に指定しても有効なのは1つだけです。当然のことですが...
どれが有効になるかは 以下のように vertical 属性の値によって変わります。

  • vertical = false の場合、columns > width > rows > height の順に優先される
  • vertical = true の場合、rows > height > columns > width の順に優先される

と言うことで...
優先順位のことは忘れて、rows, colums, width, height の指定は、必ず一つにしましょう。
何の意味もないので...

3. rows, columns, width, height のデフォルト値は -1

rows, columns, width, height に -1 を指定した場合、デフォルト (何も指定しなかった場合) と同じレイアウトになるようです。
以下のようにすれば、条件が真の場合だけ 任意の値を指定することができます。

Tile {
    width: if (condition) width else -1
       :
}

ただし、以下のように bind してしまうと、条件が偽の場合でもデフォルトのレイアウトにはならないようです。

Tile {
    width: bind if (condition) width else -1
      :
}