テーブルコンポーネント、配列、数値/日付のフォーマット
- 従業員一覧サンプル

では次に、テーブルコンポーネントを用いたアプリケーションを紹介する。テーブルコンポーネントによるデータの一覧表示は、ビジネスユースのアプリケーションなどでは非常によく利用されることから、サンプルとして取り上げてみたい。

このサンプルは非常に単純で、起動すると同時に従業員一覧(データ自体は、配列変数としてプログラム中にハードコードされている)が表示されるだけだ。

従業員一覧サンプル

このサンプルにおける一番のポイントは、テーブルコンポーネントの使用方法だ。 併せて、さらに進んだ増分評価の使用方法やformat as演算子といったものも解説している。

サンプルのソースコードを以下に示す。単純な例だけあって、50行弱の短いプログラムにまとまっている。

リスト5:examples/employeeview/EmployeeView.fx

package examples.employeeview;

import javafx.ui.*;

// モデルクラス「従業員」
class Employee {
    attribute id:Integer;           // 従業員番号
    attribute name:String;          // 従業員名
    attribute annualIncome:Integer; // 年収(単位:万円)
}

// (1) 全従業員を表す配列変数
var employees:Employee* = [
    {id: 1, name: "山田太郎", annualIncome: 600},
    {id: 2, name: "田中次郎", annualIncome: 700},
    {id: 3, name: "佐藤花子", annualIncome: 420},
    {id: 4, name: "村上三郎", annualIncome: 1040},
    {id: 5, name: "加藤良子", annualIncome: 840},
];

// メインウィンドウの作成
Frame {
    // (2) ウィンドウタイトル
    title: bind "従業員一覧(全{sizeof employees}件)"
    // (3) テーブルコンポーネントの使用
    content: Table {
        columns: [
            TableColumn { text: "従業員番号" },
            TableColumn { text: "名前" },
            TableColumn { text: "年収", alignment: TRAILING }
        ],
        // (4) テーブルのセルを、配列の内容にバインド
        cells: bind foreach (employee in employees)
            [
                TableCell {
                    text: bind "{employee.id}"
                },
                TableCell {
                    text: bind employee.name
                },
                TableCell {
                    // (5) format as演算子を用いた数値のフォーマット
                    text: bind "\\{(employee.annualIncome * 10000) format as <<#,##0>>}"
                },
            ]
    }
    centerOnScreen: true, visible: true
};

ポイントは以下の通りだ。

(1) 配列変数の作成を行っている。JavaFX Scriptにおける配列について詳しく説明するのは、別の機会に譲ることにする。とりあえず、配列の生成は「[]」(大かっこ)の中に要素をカンマ区切りで列挙することで行うことができ、この例では「従業員番号」「従業員名」「年収」を属性に持つモデルクラスEmployeeのインスタンスを複数格納したものだとご認識いただきたい。

(2) ウィンドウのタイトルを、{sizeof employees}という式を含む文字列にバインドしている。JavaFXでは、Javaとは異なり配列自身が長さの情報を持ってはおらず、「sizeof」演算子を用いて配列長を取得する。配列に対して使用できる演算子は、他には「indexof」演算子がある。これは、「値 indexof 配列」のように用いて、ある値が配列中でどの位置にあるかを取得するための演算子だ。

(3) テーブルコンポーネント(javafx.ui.Table)コンポーネントを使用し、従業員の一覧を作成している。Tableクラスの使用法は簡単で、以下のようなポイントがある。

  • columns属性に、javafx.ui.TableColumnの配列を代入して、カラムの情報をテーブルコンポーネントに伝える。TableColumnは、カラムヘッダに表示するテキスト(text属性)、列データの表示位置(alignment属性。値はTRAILING:右寄せ、CENTER:中央、LEADING:左寄せ となる)、幅(width属性)などを指定できる
  • cells属性に、javafx.ui.TableCellの配列を代入することで、テーブルのセルを表示できる。TableCellクラスでは、主にセルに表示するテキスト(text属性)を設定する。1行に何個のセルを表示するかはcolumnsで指定したTableColumnの数によって決まる

つまり、Tableコンポーネントの構造を疑似的に表すと以下のようになる。

Table {
  columns: TableColumn*  // テーブルの列数分要素を持つ配列
  cells: TableCell*      // テーブルのセル数分要素を持つ配列
}

(4) テーブルのセルを表すcells属性がバインドされているのは、foreach演算子を使用したステートメントだ。foreach演算子は、配列の内容をループしながら新しいオブジェクト(ここではTableCellの配列)を生成するための式だ(厳密に言うとforeachはより多くの機能を持つが、その説明は省略)。このようなバインドが行われていることにより、ステートメント内で参照されている属性(employeesemployee.idemployee.nameemployee.annualIncome)に変更があった場合、即座にテーブルの表示内容は変更される。

(5) 年収をテーブルのセルに表示する部分であり、ここでは「Employee.annualIncomeの値が400だった場合、"\4,000,000"とセルに表示する」というコードになっている。ポイントは以下のとおり。

  • 文字'\'を表すために、文字列リテラル内で"\"とエスケープしている。「\」(エスケープ文字)、「"」(文字列リテラルの囲み文字)、「'」(ダブルクォートと同じく文字列リテラルの囲み文字に利用できる)、「{」(JavaFX式の始まり)といった文字はこのようにエスケープが必要となる

  • format as演算子。JavaFXには「オブジェクト/数値/日付→文字列」の変換を行う仕組みが言語仕様に組み込まれている。format as演算子の使用法は、「フォーマット対象 format as フォーマット識別子」 となり、フォーマット対象の型とフォーマット識別子の内容に応じてjava.util.Formatterjava.text.DecimalFormatjava.text.SimpleDateFormatのどれかが選択される(フォーマット形式を「識別子」で指定することに注意。サンプルでも、「<< >>」で囲んで指定している。これにより、フォーマット形式の妥当性がコンパイル時にチェックされるのがこの仕組みの素晴らしいところだ)

このサンプルのまとめ

このサンプルで最も重要なポイントは、テーブルコンポーネントのcells属性に対して、複雑なステートメントを指定しているところだ。実際、関数やオペレーションといったコードでさえも増分評価の対象とすることができる。

他にも、テーブルコンポーネントの使用法、format as演算子などの重要なポイントは完璧に押さえておきたい。