2012-10-12 16 views
12

Jak zrobić uderzenie klawisza Tab w TextArea przechodzi do następnej kontrolki?Nawigacja klawiszem Tab w JavaFX TextArea

Mogę dodać słuchacza do naciśniętego przycisku cath de key, ale w jaki sposób sprawić, aby kontrolka TextArea utraciła ostrość (bez znajomości następnego pola w łańcuchu, który ma być skupiony)?

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

Odpowiedz

8

Kod ten trawers skupić jeśli klawisz TAB i włóż kartę, jeśli po naciśnięciu przycisku 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(); 
       } 

      } 
     } 
    }); 
+3

Jeden drobny problem: powinien mieć sprawdzenie zdarzenia.isShiftDown(), które powinno wywoływać "TraversePrevious", a nie "TraverseNext". –

+4

Przynajmniej dla JavaFX 8, SkinBase powinien zostać zmieniony na TextAreaSkin. – tunabot

12

używam Poligon-metody

@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(); 
    } 
} 
+0

To rozwiązanie jest najczystsze, jakie znalazłem. Chociaż nie jest konieczne definiowanie go dla TextField, ponieważ jest to już ustawienie domyślne (przynajmniej w Javie 8). – codepleb

+0

Problem polega jednak na tym, że zmusza Cię do rozszerzenia TextArea - niezbyt wygodne, jeśli używasz Scene Builder. – User

+0

... faktycznie @Override mnie wyrzucił, nie ma metody obsługi, którą można przesłonić w TextArea, więc domyślam się, że jest to zwykła metoda obsługi. Mimo to, chciałbym, żeby był łatwiejszy sposób - no cóż. – User

0

Miałem ten sam problem i lubię metody trawersowania, których używa Tom. Ale chcę również wstawić kartę po naciśnięciu klawisza Ctrl + Tab.

Wezwanie

behavior.callAction("InsertTab"); 

praca doesnt z JavaFX8. Spojrzenie w klasie TextAreaBehaviour pokazało mi, że istnieje teraz akcja "TraverseOrInsertTab".

Jednak myślę, że ten rodzaj wywoływania akcji jest dość niestabilny w kilku wersjach java, ponieważ opiera się na ciągu, który jest przekazywany.

Więc zamiast metody callAction(), użyłem

textArea.replaceSelection("\t"); 
1

Jeśli inne rozwiązanie dla Tab - błąd regulacji ostrości. Domyślne zachowanie obszaru tekstowego dla klawisza CTRL + TAB jest przeniesieniem fokusu do następnej kontrolki. Więc zamieniłem wydarzenie klawisza TAB na wydarzenie CTRL + TAB, a gdy użytkownik trafi CTRL + TAB, znak tabulacji zostanie wstawiony do TextArea.

Moje pytanie: czy można wystrzelić zdarzenie w filtrze zdarzeń? Czy można zamienić tekst KeyEvent na FOCUS_EVENT_TEXT, aby mieć wskazanie, czy jest to zdarzenie generowane przez użytkownika, czy zdarzenie utworzone w filtrze zdarzenia.

Filtr wydarzenie:

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

obsługi zdarzenia:

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

Zainspirowany poprzednich odpowiedzi i bardzo podobnej sprawie, zbudowałem następujące klasy:

/** 
* 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(); 
      } 
     } 
    } 
} 

Po prostu nie widziałem konieczności h andling w kontekście TextField, więc usunąłem tę część.

Następnie klasa ta może być bardzo łatwo wykorzystane w sposób opisany przez User:

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

I cała rzecz działa jak czar :)

2

Jako Java 9 (2017), większość odpowiedzi na tej stronie nie działa, ponieważ nie możesz już więcej wykonać.

To działa:

@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) { } 
     } 
    } 

To działa również:

@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);    
     } 
    } 

Zarówno symulować naciśnięcie CTRL+TAB gdy użytkownik naciśnie TAB. Domyślne zachowanie TextArea dla CTRL+TAB przenosi fokus do następnej kontrolki. Pamiętaj, że drugi kod opiera się na odpowiedzi Johana De Schuttera.

Powiązane problemy