JavaFXTextArea中的选项卡键导航

JavaFXTextArea中的选项卡键导航,java,user-interface,javafx-2,javafx,Java,User Interface,Javafx 2,Javafx,如何使点击文本区域中的Tab键导航到下一个控件 我可以向cath de key pressed事件添加一个侦听器,但是如何使te TextArea控件失去焦点(而不知道要聚焦的链中的下一个字段) 此代码在按TAB键时遍历焦点,在按CONTROL+TAB键时插入TAB键 textArea.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() { @Override public

如何使点击文本区域中的Tab键导航到下一个控件

我可以向cath de key pressed事件添加一个侦听器,但是如何使te TextArea控件失去焦点(而不知道要聚焦的链中的下一个字段)


此代码在按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();
                }

            }
        }
    });
textArea.addEventFilter(按下KeyEvent.KEY\u,新建EventHandler()){
@凌驾
公共无效句柄(KeyEvent事件){
if(event.getCode()==KeyCode.TAB){
SkinBase skin=(SkinBase)textArea.getSkin();
if(TextAreaBehavior的skin.getBehavior()实例){
TextAreaBehavior=(TextAreaBehavior)skin.getBehavior();
if(event.isControlDown()){
behavior.callAction(“InsertTab”);
}否则{
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");
不适用于JavaFX8。查看TextAreaBehavior类后,我发现现在有一个“TraverseOrInsertTab”操作

但是,我认为这种操作调用在几个java版本中是非常不稳定的,因为它依赖于传递的字符串

因此,我没有使用callAction()方法,而是使用

textArea.replaceSelection("\t");

如果选项卡焦点问题有不同的解决方案。 CTRL+TAB键的文本区域的默认行为是将焦点移动到下一个控件。因此,我将TAB键事件替换为CTRL+TAB键事件,当用户点击CTRL+TAB键时,文本区域中会插入一个TAB字符

我的问题:可以在事件筛选器中触发事件吗?并且可以用焦点事件文本替换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);
        }
    }
}
public类TextAreaTabToFocusEventHandler实现EventHandler
{
私有静态最终字符串FOCUS\u EVENT\u TEXT=“TAB\u TO\u FOCUS\u EVENT”;
@凌驾
公共无效句柄(最终KeyEvent事件)
{
如果(!KeyCode.TAB.equals(event.getCode()))
{
返回;
}
//处理按下TAB键或TAB+CTRL键的事件
//因此,如果按下ALT、SHIFT或任何其他修改键,则不要处理该事件
if(event.isAltDown()| | | event.isMetaDown()| | | event.isShift down())
{
返回;
}
if(!(event.getSource()instanceof TextArea))
{
返回;
}
final TextArea TextArea=(TextArea)event.getSource();
if(event.isControlDown())
{
//如果事件文本包含特殊焦点事件文本
//=>不要使用事件,让默认行为(=将焦点移动到下一个控件)发生。
//
//如果焦点事件文本不存在,则表示用户按下了CTRL+TAB键,
//然后使用事件并用制表符插入或替换所选内容
if(!FOCUS\u EVENT\u TEXT.equalsIgnoreCase(EVENT.getText()))
{
event.consume();
textArea.replaceSelection(“\t”);
}
}
其他的
{
//CTRL+TAB键的文本区域的默认行为是将焦点移动到下一个控件。
//因此,我们使用TAB键事件,并使用CTRL+TAB键触发一个新事件。
event.consume();
final KeyEvent tabControlEvent=新的KeyEvent(event.getSource()、event.getTarget()、event.getEventType()、event.getCharacter(),
焦点\事件\文本,EVENT.getCode(),EVENT.isShiftDown(),true,EVENT.isAltDown(),EVENT.isMetaDown();
textArea.firevent(tabControlEvent);
}
}
}

受前面答案的启发,针对一个非常类似的案例,我构建了以下类:

/**
*处理tab/shift tab键击以导航到其他字段,
*ctrl-tab可在文本区域中插入制表符。
*/
公共类TabTraversalEventHandler实现EventHandler{
@凌驾
公共无效句柄(KeyEvent事件){
if(event.getCode().equals(KeyCode.TAB)){
Node Node=(Node)event.getSource();
if(TextArea的节点实例){
TextAreaSkin皮肤=(TextAreaSkin)((TextArea)节点).getSkin();
如果(!event.isControlDown()){
//选项卡或shift选项卡=>导航操作
if(event.isShiftDown()){
skin.getBehavior().traversePrevious();
}否则{
skin.getBehavior().traverseNext();
}
}否则{
//Ctrl-Tab=>在文本区域中插入制表符
TextArea TextArea=(TextArea)节点;
textArea.replaceSelection(“\t”);
}
event.consume();
}
}
}
}
我只是没有看到在文本字段上下文中处理tab的必要性,所以我删除了这个部分

然后,该类可以很容易地使用,如下所述:

TextArea myTextArea=newtextarea();
mytTextArea.addEventFilter(按下KeyEvent.KEY_,新选项卡TraversalEventHandler());
整个过程就像一个魔咒:)

从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);            
        }
    }
这也是
@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);            
        }
    }