简体   繁体   English

当我为JPanel使用Key Binding时,为什么我不能获得KeyEvent.VK_TAB

[英]Why can't I get KeyEvent.VK_TAB when I use Key Binding for a JPanel

I will print related info if users focus on current window and press a key. 如果用户关注当前窗口并按一个键,我将打印相关信息。 However, it works for some keys like 'a' but not for 'tab'. 但是,它适用于某些键,如'a'但不适用于'tab'。 Here is a simple demo: 这是一个简单的演示:

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");
                }
            });     
        }   
    }
}

What can I do to reach it? 我能做些什么来达到它? Thanks in advance. 提前致谢。

Quote from How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features) (suggested by @alex2410(link to @camickr post) and @mKorbel): 引用如何使用焦点子系统(Java™教程>使用JFC / Swing创建GUI>使用其他Swing功能) (由@ alex2410(链接到@camickr帖子)和@mKorbel建议):

In most Look and Feel models, components are navigated using the Tab and Shift-Tab keys. 在大多数外观和感觉模型中,使用Tab和Shift-Tab键导航组件。 These keys are the default focus traversal keys and can be changed programmatically. 这些键是默认的焦点遍历键,可以通过编程方式进行更改。
... ...
Tab shifts the focus in the forward direction. Tab将焦点向前移动。 Shift-Tab moves the focus in the backward direction. Shift-Tab向后移动焦点。 Tabbing moves the focus through the buttons into the text area. Tabbing将焦点通过按钮移动到文本区域。 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. 附加标签将光标移动到文本区域内,但不会移出文本区域,因为在文本区域内,Tab不是焦点遍历键。 However, Control-Tab moves the focus out of the text area and into the first text field. 但是,Control-Tab将焦点移出文本区域并移动到第一个文本字段中。 Likewise, Control-Shift-Tab moves the focus out of the text area and into the previous component. 同样,Control-Shift-Tab将焦点移出文本区域并移动到上一个组件中。
... ...
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. 约定使用Control键将焦点移出任何以特殊方式处理Tab的组件,例如JTable。
You have just received a brief introduction to the focus architecture. 您刚刚收到了焦点架构的简要介绍。 If you want more details, see the specification for the Focus Subsystem . 如果您需要更多详细信息,请参阅Focus子系统的规范。

So if you want to make the Tab KeyBinding action work in the panel, you need to remove the Tab key focus navigation from the panel. 因此,如果要使Tab键绑定操作在面板中起作用,则需要从面板中删除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");
      }
    });
  }
}
  • interesting issue with TAB, looks like as bug, because isn't possible to get, capture the KeyChar from TAB without using Shift_TAB before, event from TAB is somehow consumed elsewhere, no idea whats happened 有趣的问题与TAB,看起来像bug,因为是不可能获得,从TAB捕获KeyChar而不使用Shift_TAB之前,来自TAB的事件以某种方式消耗在别处,不知道发生了什么

  • my view - there is an issue with Focus because key TAB is used by Native OS and as built_in KeyBindings in Swing, 我的观点 - Focus存在一个问题,因为本地操作系统使用了密钥TAB,而在Swing中使用了build_in KeyBindings,

  • opposite issue with TAB and Shift_TAB in question Java Swing: how to stop unwanted shift-tab keystroke action 问题与TAB和Shift_TAB相反的问题Java Swing:如何阻止不需要的shift-tab击键动作

  • maybe someone has explanation how to catch a TAB event 也许某人有解释如何捕捉TAB事件

  • TAB is used as KeyBindings (built_in in API) for many JComponents or navigations inside Container contains more than one JComponent 对于许多JComponents,TAB用作KeyBindings(在API中为built_in),或者Container内的导航包含多个JComponent

funny output from AWTEventListener (win8_64b/Java7_xxx) 来自AWTEventListener的有趣输出(win8_64b / Java7_xxx)

     is typed //tab is pressed
     is typed
     is typed
     is typed
     is typed
     is typed
     is typed
     is typed
     is typed
 is typed //shift is pressed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
 is typed
     is typed // tab is pressed again
     is typed
     is typed
     is typed
 is typed //:-) nobody knows something from milky way
 is typed
     is typed
shift tab is typed //now is tab event unlocked for Container in Swing
shift tab is typed
shift tab is typed
ctrl tab is typed
ctrl tab is typed
ctrl tab is typed
tab is typed // now is possible, finally TAB is unlocked and firing an event
tab is typed
tab is typed

from code 来自代码

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

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

//https://stackoverflow.com/q/24800417/714968
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);
        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
            @Override
            public void eventDispatched(AWTEvent event) {
                if (event instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) event;
                    System.out.println(ke.getKeyChar() + " is typed");
                }
            }
        }, AWTEvent.KEY_EVENT_MASK);
    }

    @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 = "TAB";
            this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(tabString), tabString);
            //getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
            this.getActionMap().put(tabString, new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // TODO Auto-generated method stub
                    System.out.println("tab is typed");
                }
            });
            String tabShiftString = "shift TAB";
            this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(tabShiftString), tabShiftString);
            //getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
            this.getActionMap().put(tabShiftString, new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // TODO Auto-generated method stub
                    System.out.println("shift tab is typed");
                }
            });
            String ctrlShiftString = "ctrl TAB";
            this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(ctrlShiftString), ctrlShiftString);
            //getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
            this.getActionMap().put(ctrlShiftString, new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // TODO Auto-generated method stub
                    System.out.println("ctrl tab is typed");
                }
            });
        }
    }
} 

I think it should work if you put 我认为如果你放,它应该工作

setFocusTraversalKeysEnabled(false);

in your MainPanel constructor. 在您的MainPanel构造函数中。 At least it works for eg addKeyListener(...); 至少它适用于例如addKeyListener(...);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM