java - 为什么在为 JPanel 使用键绑定(bind)时无法获取 KeyEvent.VK_TAB

标签 java swing awt key-bindings

如果用户关注当前窗口并按下一个键,我将打印相关信息。但是,它适用于某些键,例如“a”,但不适用于“tab”。这是一个简单的演示:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;


public class KeyBindingTest {
    public static void main(String[] args) {
        KeyBindingTest test = new KeyBindingTest();
        test.createUI();
    }

    public void createUI(){
        JFrame frame = new JFrame("KeyBinding Test");
        MainPanel mainPanel = new MainPanel();
        frame.add(mainPanel,BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    @SuppressWarnings("serial")
    class MainPanel extends JPanel{
        public MainPanel(){
            setPreferredSize(new Dimension(200, 200));
            //========================key binding============================
            requestFocusInWindow();
            String aString = "aStr";
            getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), aString);
            getActionMap().put(aString, new AbstractAction() {          
                @Override
                public void actionPerformed(ActionEvent e) {
                    // TODO Auto-generated method stub
                    System.out.println("a is typed");
                }
            });     

            String tabString = "tabStr";
            getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
            getActionMap().put(tabString, new AbstractAction() {            
                @Override
                public void actionPerformed(ActionEvent e) {
                    // TODO Auto-generated method stub
                    System.out.println("tab is typed");
                }
            });     
        }   
    }
}

我该怎么做才能达到目标?提前致谢。

最佳答案

引自 How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features) (@alex2410(链接到@camickr 帖子)和@mKorbel 建议):

In most Look and Feel models, components are navigated using the Tab and Shift-Tab keys. These keys are the default focus traversal keys and can be changed programmatically.
...
Tab shifts the focus in the forward direction. Shift-Tab moves the focus in the backward direction. Tabbing moves the focus through the buttons into the text area. Additional tabbing moves the cursor within the text area but not out of the text area because, inside a text area, Tab is not a focus traversal key. However, Control-Tab moves the focus out of the text area and into the first text field. Likewise, Control-Shift-Tab moves the focus out of the text area and into the previous component.
...
The Control key is used by convention to move the focus out of any component that treats Tab in a special way, such as JTable.
You have just received a brief introduction to the focus architecture. If you want more details, see the specification for the Focus Subsystem.

所以如果你想让Tab键绑定(bind) Action 在面板中起作用,你需要从面板中移除Tab键焦点导航。

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

//http://stackoverflow.com/q/24800417/714968
public class KeyBindingTest3 {
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame("KeyBinding Test");
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new MainPanel());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class MainPanel extends JPanel {
  public MainPanel() {
    super();
    //@see JTable constructor
    Set<KeyStroke> forwardKeys = new HashSet<KeyStroke>(1);
    forwardKeys.add(KeyStroke.getKeyStroke(
        KeyEvent.VK_TAB, InputEvent.CTRL_MASK));
    setFocusTraversalKeys(
        KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardKeys);

    Set<KeyStroke> backwardKeys = new HashSet<KeyStroke>(1);
    backwardKeys.add(KeyStroke.getKeyStroke(
        KeyEvent.VK_TAB, InputEvent.SHIFT_MASK | InputEvent.CTRL_MASK));
    setFocusTraversalKeys(
        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, backwardKeys);

    setPreferredSize(new Dimension(200, 200));

    String aString = "aStr";
    getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), aString);
    getActionMap().put(aString, new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("a is typed");
      }
    });
    String tabString = "TAB";
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
      KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
    getActionMap().put(tabString, new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("tab is typed");
      }
    });
  }
}

关于java - 为什么在为 JPanel 使用键绑定(bind)时无法获取 KeyEvent.VK_TAB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24800417/

相关文章:

java - 通过图形类时遇到问题

java - 全屏独占模式下的 AWT 框架在窗口弹出对话框中最小化

java - JList选择随机跳转到前一个索引

java - 如何使 AbstractListModel 子类对 Collection 更改使用react?

java - 我如何使用 MapStore 实现将 hazelcast 存储在我的数据库中

Java Map<> 可以使用内在类型吗?

java - Google Web Toolkit 是否类似于 AWT 和 Swing

java - 我可以使用 BufferedReader 并在 actionListener 类中创建一个数组吗?

java - Infinispan:类已更改且反序列化不起作用

java - 如何修改火车时刻表解析代码以考虑跳过特定车站的火车?