JavaFX の TableView を試してみた。

今日は TableView を試してみました。

もちろん今回も JavaFX 2で始めるGUI開発 を参考にさせていただいてます。

この記事のサンプルのままだと面白みが減ってしまうので少し変えてます。

といっても大したことは出来るはずがありません。

何故なら今日初めて TableView を触ったからです。(^_^;)

そういうことでこんなのができました。

ControlsFX の Rating も使ってみました。

1

 

選択時に TextArea に各項目を表示させてみました。

2

3

4

 

Title と Author を編集可能としました。

6

 

Title と Author はソート可能の設定としました。

Rating は挫折しました。(>_<。)

7

 

Rating を変更できるようにしました。(変更できないようにする方法が解らなかった)

8

9

 

以上のように簡単なことしかやっていません。

今回テーブルの選択位置変更イベントの取得に ChangeListener を使っていたのですが null が来るのでどうしたものかと悩んでました。

そこで InvalidationListener を使ってみました。

ただ InvalidationListener を使っても選択位置変更イベント時に null はやってきます。

つまり、null チェックは必要だということですね。

私の直感によると(何故調べない)選択位置変更時に古い値を null にしてから新しい値を取得しているんじゃないかと思います。

でも、InvalidationListener はBeanが実際に使われるときに変更のチェックを行うイベントなのでこちらのほうが良いそうです。

まだ情報収集が足らないのでいろいろ躓いて半泣き状態になってしまいますがプログラムが動いてくれると素直によろこべます。

詳しい内容は先述しました私が参考にしているサイトに詳しい解説があります。

ただ私がおもしろ半分で追加したことは載っていませんのでこのプログラムのコードを晒しときます。

初めての TableView なので間違いがあればご指摘くださいませ。

package jp.yucchi.booktable;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class BookTable extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("BookTableView.fxml"));

        Scene scene = new Scene(root);
        stage.setTitle("Book Table");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}
package jp.yucchi.booktable;

import org.controlsfx.control.Rating;

public class Book {

    private String title;
    private String author;
    private Rating rating;

    public Book(String title, String author, Rating rating) {
        this.title = title;
        this.author = author;
        this.rating = rating;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Rating getRating() {
        return rating;
    }

    public void setRating(Rating rating) {
        this.rating = rating;
    }

}

package jp.yucchi.booktable;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Orientation;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.Callback;
import org.controlsfx.control.Rating;

public class BookTableViewController implements Initializable {

    @FXML
    private TableView table;

    @FXML
    private TableColumn titleColumn;

    @FXML
    private TableColumn authorColumn;

    @FXML
    private TableColumn ratingColumn;

    @FXML
    private TextArea textArea;

    ObservableList books = FXCollections.observableArrayList(
            new Book("創る Java", "きしだ なおき", makeRating(1.0)),
            new Book("Effective Java", "Joshua Bloch", makeRating(5.0)),
            new Book("JAVA PUZZLERS", "Joshua Bloch, Neal Gafter", makeRating(3.0)));

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        table.setItems(books);
        titleColumn.setCellValueFactory(
                new PropertyValueFactory<>("title"));
        authorColumn.setCellValueFactory(
                new PropertyValueFactory<>("author"));
        ratingColumn.setCellValueFactory(
                new PropertyValueFactory<>("rating"));

        Callback, TableCell> titleFactory
                = TextFieldTableCell.forTableColumn();
        titleColumn.setCellFactory(titleFactory);
        titleColumn.setOnEditCommit((TableColumn.CellEditEvent event) -> {
            Book book = event.getTableView().getItems().get(event.getTablePosition().getRow());
            book.setTitle(event.getNewValue());
        });
        Callback, TableCell> authorFactory
                = TextFieldTableCell.forTableColumn();
        authorColumn.setCellFactory(authorFactory);
        authorColumn.setOnEditCommit((TableColumn.CellEditEvent event) -> {
            Book book = event.getTableView().getItems().get(event.getTablePosition().getRow());
            book.setAuthor(event.getNewValue());
        });

        TableView.TableViewSelectionModel selectionModel = table.getSelectionModel();
        selectionModel.selectedItemProperty().addListener((Observable observable) -> {
            if (selectionModel.getSelectedItem() != null) { // これ必要
                textArea.appendText(selectionModel.getSelectedItem().getTitle() + " : "
                        + selectionModel.getSelectedItem().getAuthor() + "  Rating "
                        + selectionModel.getSelectedItem().getRating().getRating() + "\n");
            }
        });

    }

    private Rating makeRating(double rate) {
        Rating rating = new Rating();
        rating.setOrientation(Orientation.HORIZONTAL);
        rating.setUpdateOnHover(false);
        rating.setPartialRating(false);
        rating.setRating(rate);
        return rating;

    }

}