2012-10-12 18 views
12

TextAreaのタブキーを押して次のコントロールに移動する方法を教えてください。JavaFX TextAreaのタブキーナビゲーション

私はcath de key pressedイベントにリスナーを追加できますが、フォーカスを失うようにTextAreaコントロールを作成するにはどうすればいいですか(フォーカスするチェーンの次のフィールドを知らずに)

@FXML protected void handleTabKeyTextArea(KeyEvent event) { 
    if (event.getCode() == KeyCode.TAB) { 
     ... 
    } 
} 

答えて

8

このコードは、私が

@Override 
public void handle(KeyEvent event) { 
    if (event.getCode().equals(KeyCode.TAB)) { 
     Node node = (Node) event.getSource(); 
     if (node instanceof TextField) { 
      TextFieldSkin skin = (TextFieldSkin) ((TextField)node).getSkin(); 
      if (event.isShiftDown()) { 
       skin.getBehavior().traversePrevious(); 
      } 
      else { 
       skin.getBehavior().traverseNext(); 
      }    
     } 
     else if (node instanceof TextArea) { 
      TextAreaSkin skin = (TextAreaSkin) ((TextArea)node).getSkin(); 
      if (event.isShiftDown()) { 
       skin.getBehavior().traversePrevious(); 
      } 
      else { 
       skin.getBehavior().traverseNext(); 
      } 
     } 

     event.consume(); 
    } 
} 
+3

1つの軽微な問題:「TraverseNext」ではなく「TraversePrevious」を呼び出すevent.isShiftDown()のチェックが必要です。 –

+4

少なくともJavaFX 8では、SkinBaseをTextAreaSkinに変更する必要があります。 – tunabot

12

を押した場合にタブを挿入するトラバース私は同じ問題を持っていたし、私は好きTomが使用するトラバースメソッド。 しかし、Ctrl + Tabを押したときにタブを挿入したいと思っています。

JavaFX8とのコール

behavior.callAction("InsertTab"); 

doesn't作品。 TextAreaBehaviourクラスの中には、 "TraverseOrInsertTab"アクションがあります。

しかし、このようなアクション呼び出しは、渡される文字列に依存するため、いくつかのJavaバージョンではかなり不安定であると思います。だからではなくcallAction()メソッドの

は、私が使用

textArea.replaceSelection("\t"); 
+0

このソリューションは私が見つけた最もクリーンです。 TextFieldにはこれを定義する必要はありませんが、これは既にデフォルトです(少なくともJava 8では)。 – codepleb

+0

問題ですが、TextAreaを拡張する必要があります。Scene Builderを使用する場合はあまり便利ではありません。 – User

+0

...実際に@Overrideは私を捨てました.TextAreaでオーバーライドするハンドルメソッドはありません。だから、これは単なる正規のハンドラメソッドだと思います。それでも、簡単な方法があることを願っています。 – User

0

トラバース・メソッドを使用するTABキーを押した場合に注力し、CONTROL + TAB

textArea.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() { 
     @Override 
     public void handle(KeyEvent event) { 
      if (event.getCode() == KeyCode.TAB) { 
       SkinBase skin = (SkinBase) textArea.getSkin(); 
       if (skin.getBehavior() instanceof TextAreaBehavior) { 
        TextAreaBehavior behavior = (TextAreaBehavior) skin.getBehavior(); 
        if (event.isControlDown()) { 
         behavior.callAction("InsertTab"); 
        } else { 
         behavior.callAction("TraverseNext"); 
        } 
        event.consume(); 
       } 

      } 
     } 
    }); 
1

もしタブの異なる溶液 - フォーカスの問題。 Ctrl + TabキーのTextAreaの既定の動作は、フォーカスを次のコントロールに移動することです。だから私はTabキーイベントをCTRL + TABキーイベントに置き換えました。そして、ユーザーがCTRL + TABを押すと、タブ文字がTextAreaに挿入されます。

私の質問:イベントフィルタでイベントを発生させても問題ありませんか?また、ユーザーが生成したイベントであるか、イベント・フィルターで作成されたイベントであるかを示すために、KeyEventのテキストをFOCUS_EVENT_TEXTに置き換えても問題ありません。

イベントフィルタ:

javafx.scene.control.TextArea textArea1 = new javafx.scene.control.TextArea(); 
textArea1.addEventFilter(KeyEvent.KEY_PRESSED, new TextAreaTabToFocusEventHandler()); 

イベントハンドラ:

public class TextAreaTabToFocusEventHandler implements EventHandler<KeyEvent> 
{ 
    private static final String FOCUS_EVENT_TEXT = "TAB_TO_FOCUS_EVENT"; 

    @Override 
    public void handle(final KeyEvent event) 
    { 
     if (!KeyCode.TAB.equals(event.getCode())) 
     { 
      return; 
     } 

     // handle events where the TAB key or TAB + CTRL key is pressed 
     // so don't handle the event if the ALT, SHIFT or any other modifier key is pressed 
     if (event.isAltDown() || event.isMetaDown() || event.isShiftDown()) 
     { 
      return; 
     } 

     if (!(event.getSource() instanceof TextArea)) 
     { 
      return; 
     } 

     final TextArea textArea = (TextArea) event.getSource(); 
     if (event.isControlDown()) 
     { 
      // if the event text contains the special focus event text 
      // => do not consume the event, and let the default behaviour (= move focus to the next control) happen. 
      // 
      // if the focus event text is not present, then the user has pressed CTRL + TAB key, 
      // then consume the event and insert or replace selection with tab character 
      if (!FOCUS_EVENT_TEXT.equalsIgnoreCase(event.getText())) 
      { 
       event.consume(); 
       textArea.replaceSelection("\t"); 
      } 
     } 
     else 
     { 
      // The default behaviour of the TextArea for the CTRL+TAB key is a move of focus to the next control. 
      // So we consume the TAB key event, and fire a new event with the CTRL + TAB key. 

      event.consume(); 

      final KeyEvent tabControlEvent = new KeyEvent(event.getSource(), event.getTarget(), event.getEventType(), event.getCharacter(), 
                  FOCUS_EVENT_TEXT, event.getCode(), event.isShiftDown(), true, event.isAltDown(), event.isMetaDown()); 
      textArea.fireEvent(tabControlEvent); 
     } 
    } 
} 
1

が前の回答に触発さと非常によく似たケースのために、私は次のクラスを構築しました:

/** 
* Handles tab/shift-tab keystrokes to navigate to other fields, 
* ctrl-tab to insert a tab character in the text area. 
*/ 
public class TabTraversalEventHandler implements EventHandler<KeyEvent> { 
    @Override 
    public void handle(KeyEvent event) { 
     if (event.getCode().equals(KeyCode.TAB)) { 
      Node node = (Node) event.getSource(); 
      if (node instanceof TextArea) { 
       TextAreaSkin skin = (TextAreaSkin) ((TextArea)node).getSkin(); 
       if (!event.isControlDown()) { 
        // Tab or shift-tab => navigational action 
        if (event.isShiftDown()) { 
         skin.getBehavior().traversePrevious(); 
        } else { 
         skin.getBehavior().traverseNext(); 
        } 
       } else { 
        // Ctrl-Tab => insert a tab character in the text area 
        TextArea textArea = (TextArea) node; 
        textArea.replaceSelection("\t"); 
       } 
       event.consume(); 
      } 
     } 
    } 
} 

私はhの必要性を見たことがありませんAndlingタブをTextFieldのコンテキストで使用して、この部分を削除しました。

Userによって記載されているように続いて、このクラスは非常に簡単に使用することができます。

TextArea myTextArea = new TextArea(); 
mytTextArea.addEventFilter(KeyEvent.KEY_PRESSED, new TabTraversalEventHandler()); 

を、全体の事は魔法のように動作します:)

2

のJava 9(2017)のとおり、 skin.getBehavior()をもう実行できないため、このページのほとんどの回答は機能しません。

この作品:

@Override 
public void handle(KeyEvent event) { 
    KeyCode code = event.getCode(); 

    if (code == KeyCode.TAB && !event.isShiftDown() && !event.isControlDown()) { 
     event.consume(); 
     Node node = (Node) event.getSource();    
     KeyEvent newEvent 
      = new KeyEvent(event.getSource(), 
        event.getTarget(), event.getEventType(), 
        event.getCharacter(), event.getText(), 
        event.getCode(), event.isShiftDown(), 
        true, event.isAltDown(), 
        event.isMetaDown()); 

     node.fireEvent(newEvent);    
     } 
    } 

両方のユーザがTABを押したときCTRL+TABを押すシミュレート:

@Override 
public void handle(KeyEvent event) { 
    KeyCode code = event.getCode(); 

    if (code == KeyCode.TAB && !event.isShiftDown() && !event.isControlDown()) { 
     event.consume(); 
     Node node = (Node) event.getSource(); 
     try { 
      Robot robot = new Robot(); 
      robot.keyPress(KeyCode.CONTROL.getCode()); 
      robot.keyPress(KeyCode.TAB.getCode()); 
      robot.delay(10); 
      robot.keyRelease(KeyCode.TAB.getCode()); 
      robot.keyRelease(KeyCode.CONTROL.getCode()); 
      } 
     catch (AWTException e) { } 
     } 
    } 

をこれも働きます。 CTRL+TABのTextAreaのデフォルトの動作では、フォーカスを次のコントロールに移動しています。 2番目のコードはJohan De Schutterの答えに基づいています。