簡體   English   中英

當我為JPanel使用Key Binding時,為什么我不能獲得KeyEvent.VK_TAB

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

如果用戶關注當前窗口並按一個鍵,我將打印相關信息。 但是,它適用於某些鍵,如'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");
                }
            });     
        }   
    }
}

我能做些什么來達到它? 提前致謝。

引用如何使用焦點子系統(Java™教程>使用JFC / Swing創建GUI>使用其他Swing功能) (由@ alex2410(鏈接到@camickr帖子)和@mKorbel建議):

在大多數外觀和感覺模型中,使用Tab和Shift-Tab鍵導航組件。 這些鍵是默認的焦點遍歷鍵,可以通過編程方式進行更改。
...
Tab將焦點向前移動。 Shift-Tab向后移動焦點。 Tabbing將焦點通過按鈕移動到文本區域。 附加標簽將光標移動到文本區域內,但不會移出文本區域,因為在文本區域內,Tab不是焦點遍歷鍵。 但是,Control-Tab將焦點移出文本區域並移動到第一個文本字段中。 同樣,Control-Shift-Tab將焦點移出文本區域並移動到上一個組件中。
...
約定使用Control鍵將焦點移出任何以特殊方式處理Tab的組件,例如JTable。
您剛剛收到了焦點架構的簡要介紹。 如果您需要更多詳細信息,請參閱Focus子系統的規范。

因此,如果要使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");
      }
    });
  }
}
  • 有趣的問題與TAB,看起來像bug,因為是不可能獲得,從TAB捕獲KeyChar而不使用Shift_TAB之前,來自TAB的事件以某種方式消耗在別處,不知道發生了什么

  • 我的觀點 - Focus存在一個問題,因為本地操作系統使用了密鑰TAB,而在Swing中使用了build_in KeyBindings,

  • 問題與TAB和Shift_TAB相反的問題Java Swing:如何阻止不需要的shift-tab擊鍵動作

  • 也許某人有解釋如何捕捉TAB事件

  • 對於許多JComponents,TAB用作KeyBindings(在API中為built_in),或者Container內的導航包含多個JComponent

來自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

來自代碼

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

我認為如果你放,它應該工作

setFocusTraversalKeysEnabled(false);

在您的MainPanel構造函數中。 至少它適用於例如addKeyListener(...);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM