为除JButton

时间:2018-05-20 18:46:52

标签: java swing key-bindings keyboardfocusmanager

我正在开发一个Swing应用程序,我想在其中输入密钥工作作为JFrameJButton组件和对话框之外的所有组件的tab键。为此,我将ENTER和TAB设置为默认的焦点遍历键。

KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
Set<KeyStroke> keys = new HashSet<>();
keys.add(enter);
keys.add(tab);
KeyboardFocusManager.getCurrentKeyboardFocusManager().setDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);

这样做效果很好,但我希望ENTER键在JButton和对话框上作为操作。

2 个答案:

答案 0 :(得分:1)

这是可能的,但使用另一种方式:全局事件监听器。要注册全局事件侦听器,您应该使用Toolkit类:

Toolkit.getDefaultToolkit().addAWTEventListener(listener, mask);

以下是您案例的示例:

import java.awt.AWTEvent;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class FocusTransferTest {

    public static void main(String[] args) {
        JFrame frm = new JFrame("Test focus transfer");
        JPanel panel = new JPanel();
        panel.add(new JTextField(10));
        panel.add(new JTextField(10));
        panel.add(new JTextField(10));
        JButton btn = new JButton("Press me");
        btn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(frm, "It's a message", "Info", 
                        JOptionPane.INFORMATION_MESSAGE);
            }
        });
        panel.add(btn);
        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEnterKeyListener(), 
                AWTEvent.KEY_EVENT_MASK);
        frm.add(panel);
        frm.pack();
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.setLocationRelativeTo(null);
        frm.setVisible(true);
    }

    private static class AWTEnterKeyListener implements AWTEventListener {

        @Override
        public void eventDispatched(AWTEvent event) {
            if (event instanceof KeyEvent) {
                KeyEvent key = (KeyEvent) event;
                if (key.getKeyCode() == KeyEvent.VK_ENTER  && key.getModifiersEx() == 0 
                        && key.getID() == KeyEvent.KEY_PRESSED) {
                    if (key.getComponent() instanceof AbstractButton) {
                        ((AbstractButton) key.getComponent()).doClick();
                    } else {
                        key.getComponent().transferFocus();
                    }
                }
            }
        }

    }
}

答案 1 :(得分:0)

我认为即使使用AWTEventListener的解决方案也行,我建议如果有其他解决方案,请避免使用AWTEventListener。这是因为它非常强大,它在到达真实目标之前全局拦截各种事件,所以如果中间出现任何错误(例如NullPointerException),整个应用程序将停止工作。

我建议的解决方案使用输入映射&amp;动作映射,它将Enter键的处理添加到特定容器中的任何聚焦组件。

优点:

  • 更安全,因为它只影响容器中的组件而不是所有组件。

缺点:

  • 相同的处理代码必须应用于需要此行为的所有容器,但这可以通过静态实用程序方法轻松完成。

以下是示例程序:

let commonClient = new grpc.Client(common_url, grpc.credentials.createInsecure());

commonClient.ServiceA.functionOne();

commonClient.ServiceB.functionTwo();