JavaFXのTextAreaにおけるタブの制御方法に代替無し

2018年1月31日

問題

JavaFXのTextAreaにおいて、タブキーを押した場合にタブ文字を入れるのではなく、次のフィールドにフォーカスを写してほしいのだが、タブ文字として入力されてしまう。これを以下のように制御したい。

  • タブのみの場合は次のフィールドへフォーカスを移す。
  • CTRLと同時の場合にタブ文字を入力する。
  • Shiftと同時の場合に前のフィールドにフォーカスを移す。

Java8での解決策とJava9の対応

/** これはJava8でコンパイルする */
import com.sun.javafx.scene.control.behavior.*;
import com.sun.javafx.scene.control.skin.*;
......

    textArea.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
      @SuppressWarnings("restriction")
      @Override
      public void handle(KeyEvent event) {
        if (event.getCode() != KeyCode.TAB) return;
        if (!tabTraverse) return;
        try {
          TextAreaSkin skin = (TextAreaSkin)textArea.getSkin();
          BehaviorBase<?> bb = skin.getBehavior();
          if (!(bb instanceof TextAreaBehavior)) return;
          TextAreaBehavior behavior = (TextAreaBehavior)bb;
          if (event.isControlDown()) {
            behavior.callAction("InsertTab");
          } else if (event.isShiftDown()) {
            behavior.callAction("TraversePrevious");
          } else {
            behavior.callAction("TraverseNext");
          }
          event.consume();  
        } catch (NoClassDefFoundError ex) {
          // Java9でJavaFXの仕様変更。代替策なし
        }      
      }
    });

Java9で仕様変更されており、TextAreaSkinが正規のクラスとなったのは良いのだが、getBehavior()メソッドがなくなり、同じ動作をさせることができなくなってしまった。上のコードは、Java9での実行においては単純に何もしない。