java SWT:TraverseEvent的理解塈添加TraverseListener实现Composite之间TAB键切换焦点

2019-05-25 21:34:29 浏览数 (1)

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433531

TraverseEvent遍历事件

从英文直译的话,org.eclipse.swt.events.TraverseEvent是指widget中组件遍历(切换焦点)动作发生时产生的事件

举例来说,就是当我们使用光标键,TAB/shift-TAB键,PAGE-UP/DOWN等键在按钮(Button)之间切换焦点的时候,就会产生TraverseEvent事件。

关于TraverseEven的原文说明,参见官网《org.eclipse.swt.events.TraverseEvent》

为什么Canvas下TAB不起作用?

当在Canvas中按下TAB键时, TraverseEvent#detail字段的值是SWT.TRAVERSE_TAB_NEXT ,TraverseEvent#doit 字段的值是false,这时系统的默认行为不会将这个TAB键理解为用户是想将焦点设置到下一个widget,这就意味着在Canvas中的按键侦听器(key Listener)将会收到用户敲的TAB键(SWT.TAB)—所以默认情况下,用TAB键是无法在widget之间切换焦点的。

如果要想让Composite对象支持TAB键在组件间移动焦点,就要改变系统对TAB键的行为,修改TraverseEvent#doit 字段的值为true

下面是org.eclipse.swt.widget.Control类中的traverse 方法代码,可以看到,当TraverseEvent#doittrue就会执行后续的遍历动作。

代码语言:javascript复制
boolean traverse (Event event) {
    /*
    * It is possible (but unlikely), that application
    * code could have disposed the widget in the traverse
    * event.  If this happens, return true to stop further
    * event processing.
    */
    //将TraverseEvent事件发送给所有组件
    sendEvent (SWT.Traverse, event);    
    if (isDisposed ()) return true;
    if (!event.doit) return false;
    //如果有组件将响应TraverseEvent事件并将doit置为true,就执行遍历动作。
    switch (event.detail) {
        case SWT.TRAVERSE_NONE:         return true;
        case SWT.TRAVERSE_ESCAPE:           return traverseEscape ();
        case SWT.TRAVERSE_RETURN:           return traverseReturn ();
        case SWT.TRAVERSE_TAB_NEXT:     return traverseGroup (true);
        case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false);
        case SWT.TRAVERSE_ARROW_NEXT:       return traverseItem (true);
        case SWT.TRAVERSE_ARROW_PREVIOUS:   return traverseItem (false);
        case SWT.TRAVERSE_MNEMONIC:     return traverseMnemonic (event.character);
        case SWT.TRAVERSE_PAGE_NEXT:        return traversePage (true);
        case SWT.TRAVERSE_PAGE_PREVIOUS:    return traversePage (false);
    }
    return false;
}

TraverseListener侦听器

如何将doit置为true呢?

SWT提供了一个TraverseListener接口(遍历事件侦听器),在组件上加上这个侦听器,就可以收到并处理TraverseEvent事件。

在WindowBuilder下添加TraverseListener侦听器很方便,可以如下图在组件上右键点击,找到Add event handlertraversekeyTraversed,就可以为组件添加一个TraverseListener了。

然后在侦听器中添加如下处理代码(是参照org.eclipse.ui.forms.widgets.FormText的TraverseListener代码改的):

代码语言:javascript复制
        addTraverseListener(new TraverseListener() {
            @Override
            public void keyTraversed(TraverseEvent e) {
                switch (e.detail) {
                case SWT.TRAVERSE_TAB_NEXT:
                case SWT.TRAVERSE_TAB_PREVIOUS:
                    // TAB/shift-TAB键时将doit置为true
                    e.doit = true;
                    return;
                }
            }
        });

上面的代码也可以写成这样

代码语言:javascript复制
        addListener(SWT.Traverse, new Listener() {
            @Override
            public void handleEvent(Event e) {
                switch (e.detail) {
                case SWT.TRAVERSE_TAB_NEXT:
                case SWT.TRAVERSE_TAB_PREVIOUS:
                    e.doit = true;
                    return;
                }
            }
        });

注意:不要忘记在父类中调用setTabList设置TAB list

参考资料

《SWT对于监听Tab键的理解》

《org.eclipse.swt.events.TraverseEvent》

《SWT/JFace 按键、事件、监听》

0 人点赞