如何修改JTextArea中tab键的行为?

我正在Java Swing中创建一个表单,其中一个字段是JTextArea 。 当我在所有其他字段上使用Tab键时,它会将焦点放在下一个窗口小部件上,但在JTextArea ,它会在文本中插入制表符(水平空格)。

我该如何修改此行为?

 /* This is my understanding of how tabbing works. The focus manager recognizes the following default KeyStrokes for tabbing: forwards: TAB or Ctrl-TAB backwards: Shift-TAB or Ctrl-Shift-TAB In the case of JTextArea, TAB and Shift-TAB have been removed from the defaults which means the KeyStroke is passed to the text area. The TAB KeyStroke inserts a tab into the Document. Shift-TAB seems to be ignored. This example shows different approaches for tabbing out of a JTextArea Also, a text area is typically added to a scroll pane. So when tabbing forward the vertical scroll bar would get focus by default. Each approach shows how to prevent the scrollbar from getting focus. */ import java.awt.*; import java.util.*; import java.awt.event.*; import javax.swing.*; public class TextAreaTab extends JFrame { public TextAreaTab() { Container contentPane = getContentPane(); contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); contentPane.add( nullTraversalKeys() ); contentPane.add( writeYourOwnAction() ); contentPane.add( useKeyListener() ); contentPane.add( addTraversalKeys() ); } // Reset the text area to use the default tab keys. // This is probably the best solution. private JComponent nullTraversalKeys() { JTextArea textArea = new JTextArea(3, 30); textArea.setText("Null Traversal Keys\n2\n3\n4\n5\n6\n7\n8\n9"); JScrollPane scrollPane = new JScrollPane( textArea ); // scrollPane.getVerticalScrollBar().setFocusable(false); textArea.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null); textArea.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null); return scrollPane; } // Replace the Tab Actions. A little more complicated but this is the // only solution that will place focus on the component, not the // vertical scroll bar, when tabbing backwards (unless of course you // have manually prevented the scroll bar from getting focus). private JComponent writeYourOwnAction() { JTextArea textArea = new JTextArea(3, 30); textArea.setText("Write Your Own Tab Actions\n2\n3\n4\n5\n6\n7\n8\n9"); JScrollPane scrollPane = new JScrollPane( textArea ); InputMap im = textArea.getInputMap(); KeyStroke tab = KeyStroke.getKeyStroke("TAB"); textArea.getActionMap().put(im.get(tab), new TabAction(true)); KeyStroke shiftTab = KeyStroke.getKeyStroke("shift TAB"); im.put(shiftTab, shiftTab); textArea.getActionMap().put(im.get(shiftTab), new TabAction(false)); return scrollPane; } // Use a KeyListener private JComponent useKeyListener() { JTextArea textArea = new JTextArea(3, 30); textArea.setText("Use Key Listener\n2\n3\n4\n5\n6\n7\n8\n9"); JScrollPane scrollPane = new JScrollPane( textArea ); scrollPane.getVerticalScrollBar().setFocusable(false); textArea.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_TAB) { e.consume(); KeyboardFocusManager. getCurrentKeyboardFocusManager().focusNextComponent(); } if (e.getKeyCode() == KeyEvent.VK_TAB && e.isShiftDown()) { e.consume(); KeyboardFocusManager. getCurrentKeyboardFocusManager().focusPreviousComponent(); } } }); return scrollPane; } // Add Tab and Shift-Tab KeyStrokes back as focus traversal keys. // Seems more complicated then just using null, but at least // it shows how to add a KeyStroke as a focus traversal key. private JComponent addTraversalKeys() { JTextArea textArea = new JTextArea(3, 30); textArea.setText("Add Traversal Keys\n2\n3\n4\n5\n6\n7\n8\n9"); JScrollPane scrollPane = new JScrollPane( textArea ); scrollPane.getVerticalScrollBar().setFocusable(false); Set set = new HashSet( textArea.getFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS ) ); set.add( KeyStroke.getKeyStroke( "TAB" ) ); textArea.setFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, set ); set = new HashSet( textArea.getFocusTraversalKeys( KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS ) ); set.add( KeyStroke.getKeyStroke( "shift TAB" ) ); textArea.setFocusTraversalKeys( KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, set ); return scrollPane; } class TabAction extends AbstractAction { private boolean forward; public TabAction(boolean forward) { this.forward = forward; } public void actionPerformed(ActionEvent e) { if (forward) tabForward(); else tabBackward(); } private void tabForward() { final KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); manager.focusNextComponent(); SwingUtilities.invokeLater(new Runnable() { public void run() { if (manager.getFocusOwner() instanceof JScrollBar) manager.focusNextComponent(); } }); } private void tabBackward() { final KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); manager.focusPreviousComponent(); SwingUtilities.invokeLater(new Runnable() { public void run() { if (manager.getFocusOwner() instanceof JScrollBar) manager.focusPreviousComponent(); } }); } } public static void main(String[] args) { TextAreaTab frame = new TextAreaTab(); frame.setDefaultCloseOperation( EXIT_ON_CLOSE ); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } } 

当按下键“tab”时,你可以在JTextArea的keylistener中使用“NextWidget.grabFocus()”方法

使用后一种方法,在焦点移开之前,制表符仍然会插入到JTextArea中。 如果你不想要这种行为,你可以创建一个JTextArea的子类,其isManagingFocus()方法总是返回false,而不是true。 例如:

 import javax.swing.*; public class NoTabTextArea extends JTextArea { public boolean isManagingFocus() { return false; } } 

NoTabTextArea的一个实例可以像JTextArea一样使用,除了tab键会导致焦点偏离它而不插入制表符。

您可以在主JFrameJPanel构造函数中调用以下方法。 通过调用使用: disableTabbingInTextAreas(this)

 public static void disableTabbingInTextAreas(Component component){ if(component instanceof Container && !(component instanceof JTextArea)){ for(final Component c : ((Container) component).getComponents() ){ disableTabbingInTextAreas(c); } }else if(component instanceof JTextArea){ final Component c = component; c.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) {} @Override public void keyPressed(KeyEvent e) { if(e.getKeyChar() == '\t'){ c.transferFocus(); e.consume(); } } @Override public void keyReleased(KeyEvent e) {} }); } } 
 import javax.swing.* ; import java.awt.event.* ; /** * This simple subclass of JTextArea does not allow the 'Tab' * to be pressed. Instead of putting in 3 blank spaces, the tab * will transfer focus */ /*-----------------------------------------------------------*/ /* */ /* NoTabJTextArea */ /* */ /*-----------------------------------------------------------*/ public class NoTabJTextArea extends JTextArea implements KeyListener { public NoTabJTextArea ( String text ) { super ( text ) ; initialize () ; } public NoTabJTextArea ( ) { super() ; initialize() ; } public NoTabJTextArea ( MaskDocument document ) { super ( document ) ; initialize() ; } private void initialize () { addKeyListener ( this ) ; } public void keyPressed ( KeyEvent e ) { switch ( e.getKeyCode() ) { case KeyEvent.VK_TAB : e.consume() ; transferFocus() ; break ; } } public void keyReleased ( KeyEvent e ) { switch ( e.getKeyCode() ) { case KeyEvent.VK_TAB : System.out.println ( "KEY RELEASED TAB" ) ; break ; } } public void keyTyped ( KeyEvent e ) { switch ( e.getKeyCode() ) { case KeyEvent.VK_TAB : System.out.println ( "KEY TYPED TAB" ) ; break ; } } } /* NoTabJTextArea */