takeda_san’s blog

KotlinとVRを頑張っていく方向。

JavaFXのテーブル行の文字色をまとめて設定したい

結論から書くと、次のスタイルを指定すればよい。

-fx-text-background-color

参考にしたのは下記のページ。
やはり、スタイルの設定をしたければ、まずmodenaの定義を見よ。ということに尽きる。
(以前にもtreetableの偶数行の背景色を変更する設定で、はまったときにmodenaを読みに読んで解決しました…)

stackoverflow.com

実際にプログラムを書いてみる。
使うコードはみんな大好き、oracleの解説ページ。

docs.oracle.com

setRowFactoryのところ以外は。 警告が出ているところをちょっと変えただけ。

   public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(450);
        stage.setHeight(500);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        table.setEditable(true);

        table.setRowFactory(tableView -> {
            TableRow<Person> row = new TableRow<>();
            row.setStyle("-fx-text-background-color:red");

            return row;
        });

        TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));

        TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));

        TableColumn<Person, String> emailCol = new TableColumn<>("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(new PropertyValueFactory<>("email"));

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);
        stage.show();
    }

f:id:takeda_san:20170406222047p:plain

重要なのが、ここ。

       table.setRowFactory(tableView -> {
            TableRow<Person> row = new TableRow<>();
            row.setStyle("-fx-text-background-color:red");

            return row;
        });

行の設定はtableのsetRowFactoryで行う。
カラムの中のセルの設定をcellFactoryで行うのと同じイメージ。
最初は全セルでモデルデータの値を頑張って取得して、文字色を変えようとしていたんだけど、
思えば行で設定してあげればよかったんですよね。
TableRowのsetFillでも、同じことができるかと思いきや、できない。
(-fx-text-fillでも同じ)

そのほうが、personのどれかの値が変わったときに文字色を変えたい!!!みたいなときに、updateItemをオーバーロードして更新ができる。
セルでやっていると実装の都合上、そのセル(カラム)に表示している値が更新されないとupdateItemが走らないので、実装が大変。

実際に書くとこんな感じだろうか。 イザベラさんの行だけを赤くする。

       table.setRowFactory(tableView -> {
            final TableRow<Person> row = new TableRow<Person>() {
                @Override
                protected void updateItem(Person person, boolean empty) {
                    super.updateItem(person, empty);

                    if (!empty) {
                        if ("Isabella".equals(person.firstName.getValue())) {
                            setStyle("-fx-text-background-color:red");
                        } else {
                            getStyleClass().remove("-fx-text-background-color:red");
                        }
                    }
                }
            };

            return row;
        });

スタイルの追加、削除の処理がちょっと怪しいがとりあえずは動く。

f:id:takeda_san:20170406222051p:plain

なんだかんだで、半日ほど悩んでいたが1行で事足りてしまった。
ちょっと複雑な気持ち。