ControlのSkinにRadioButtonを使う。RadioButtonには画像も表示させたい………。そんなに特別な場面ではないだろう。ところが、おそらくJavaFX8のバグと思われる妙な挙動をしたので、ここで報告しておく。すでにバグとして登録されているかはよく知らない。
問題となるソースコードは次のようなもの。基本的には、TilePaneを拡張し、子要素に二つのRadioButtonを並べたSkin2というクラスを4つ表示しているだけだ。
ただし、この二つのRadioButtonには、GraphicとしてAというラベルとBというラベルを設定している。
//import は略 public class Test extends Application{ @Override public void start(final Stage stage) throws Exception{ //-fx-skinでSkin2をskinに指定 final Control2 c2 = new Control2(); //createDefaultSkinでskinを指定 final Control3 c3 = new Control3(); //直接Skin2を表示 final Skin2 s = new Skin2(null); //もう一回表示 final Control2 c22 = new Control2(); final VBox v = new VBox(); v.setPadding(new Insets(50)); v.getChildren().addAll(c2,c3,s,c22); stage.setScene(new Scene(v)); stage.show(); } public static class Control2 extends Control{ public Control2(){ setStyle("-fx-skin:'"+Skin2.class.getName()+"'"); } } public static class Control3 extends Control{ @Override protected Skin<?> createDefaultSkin(){ return new Skin2(this); } } public static class Skin2 extends TilePane implements Skin<Control>{ Control c ; public Skin2(final Control c){ this.c = c; final RadioButton r1 = new RadioButton("a"), r2 = new RadioButton("b"); r1.setGraphic(new Label("A")); r2.setGraphic(new Label("B")); getChildren().addAll(r1,r2); r1.setSelected(true); } @Override public Control getSkinnable(){return c;} @Override public Node getNode(){return this;} @Override public void dispose(){} } public static void main(final String[] args){launch(args);} }
これを実行すると次のようになる。
最初と最後が明らかにおかしい。ボタンはないし、●は変なところに表示されているし、aと表示されていない。しかし、二つ目の「○B b」は正しく表示されている。
Skinで表示すると問題なのかと思ったが、createDefaultSkinを用いると、あら不思議、二列目のように正しく表示されている。ということは、リフレクション関連のバグ?
というわけで、どーいうことなんですかねぇ、これ。