如何使TextArea中的Tab鍵導航到下一個控件?JavaFX中的Tab鍵導航TextArea
我可以添加一個監聽器給cath按鍵按下的事件,但是如何讓te TextArea控件失去焦點(不知道鏈中下一個要被聚焦的區域)?
@FXML protected void handleTabKeyTextArea(KeyEvent event) {
if (event.getCode() == KeyCode.TAB) {
...
}
}
如何使TextArea中的Tab鍵導航到下一個控件?JavaFX中的Tab鍵導航TextArea
我可以添加一個監聽器給cath按鍵按下的事件,但是如何讓te TextArea控件失去焦點(不知道鏈中下一個要被聚焦的區域)?
@FXML protected void handleTabKeyTextArea(KeyEvent event) {
if (event.getCode() == KeyCode.TAB) {
...
}
}
如果按下Control + TAB此代碼遍歷集中,如果按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();
}
}
}
});
我用的是橫向的方法
@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();
}
}
我有同樣的問題,我喜歡Tom使用的遍歷方法。 但我也想按Ctrl + Tab時插入一個選項卡。
呼叫
behavior.callAction("InsertTab");
doesn't工作,JavaFX8。 TextAreaBehaviour類的外觀讓我知道現在有一個「TraverseOrInsertTab」操作。
但是,我認爲這種動作調用在幾個Java版本中相當不穩定,因爲它依賴於傳遞的字符串。
因此,而不是在callAction()方法中,我使用
textArea.replaceSelection("\t");
如果用於標籤不同的解決方案 - 焦點問題。 CTRL + TAB鍵的TextArea的默認行爲是焦點移動到下一個控件。因此,我用CTRL + TAB鍵事件替換了TAB鍵事件,並且當用戶點擊CTRL + TAB時,在TextArea中插入了製表符。
我的問題:可以在事件過濾器中觸發事件嗎?可以用FOCUS_EVENT_TEXT替換KeyEvent的文本,以便指示它是用戶生成的事件還是事件過濾器中創建的事件。
事件過濾器:
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);
}
}
}
由以前的答案和一個非常類似的事例的啓發,我建立了下面的類:
/**
* 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的必要性在TextField的上下文中,我刪除了這部分。
然後可以通過User描述可以非常容易地使用這個類:
TextArea myTextArea = new TextArea();
mytTextArea.addEventFilter(KeyEvent.KEY_PRESSED, new TabTraversalEventHandler());
而且整個事情就像一個魅力:)
從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();
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) { }
}
}
這也適用於:
@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);
}
}
兩個模擬按下CTRL+TAB
當用戶按下TAB
。 TextArea的默認行爲CTRL+TAB
正在將焦點移到下一個控件。請注意第二個代碼是基於Johan De Schutter的回答。
一個小問題:它應該檢查event.isShiftDown(),它應該調用「TraversePrevious」,而不是「TraverseNext」。 –
至少對於JavaFX 8,SkinBase應該更改爲TextAreaSkin。 – tunabot