JavaFXのテーブルサンプル

ネット上のJavaFXのTableViewのサンプルを見てみると、セルを指定するのに、Javaフィールドの名称を文字列で指定しているものが見受けられるのだが、もちろんこれは望ましくない。

理由を説明するのも面倒なのだが、例えばフィールド名称を変更しても、文字列の中身までは変えてくれないからだ。そもそもIDEやコンパイラは、この二つが同一のものを意味していることを認識してくれない。

正しいやり方はおそらく以下と思われる。このサンプルは、自己完結しているので、コピーしてもらえば実行できる。

import javafx.application.*;
import javafx.beans.property.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;

public class TableSample extends Application {

  public static class Row {
    SimpleStringProperty name;
    SimpleStringProperty address;
    Row(String name, String address) {
      this.name = new SimpleStringProperty(name);
      this.address = new SimpleStringProperty(address);
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public void start(Stage stage) throws Exception {

    TableView<Row> tv = new TableView<>();

    TableColumn<Row, String>nameCol = new TableColumn<>("名前");
    nameCol.setCellValueFactory(t->t.getValue().name);    
    TableColumn<Row, String>addressCol = new TableColumn<>("住所");
    addressCol.setCellValueFactory(t->t.getValue().address);    
    tv.getColumns().addAll(nameCol, addressCol);

    Row row0, row1;
    tv.getItems().addAll(
      row0 = new Row("小林", "東京都"),
      row1 = new Row("鈴木", "神奈川")
    );

    Button button = new Button("訂正");
    button.setOnAction(e -> {
      row0.name.set("中村");
    });


    BorderPane borderPane = new BorderPane();
    borderPane.setCenter(tv);
    borderPane.setBottom(button);

    stage.setScene(new Scene(borderPane));
    stage.show();
  }

  public static void main(String[]args) {
    Application.launch(TableSample.class, args);
  }
}

実行結果は以下になる。

なお、「訂正」ボタンを押すと、「小林」が「中村」に変わる。