我正在Java Swing中创建一个表单,其中一个字段是JTextArea
。当我在所有其他字段上使用 Tab 键时,它会将焦点放在下一个窗口小部件上,但在JTextArea
中,它会在文本中插入制表符(水平空格)。 / p>
如何修改此行为?
答案 0 :(得分:22)
/*
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);
}
}
答案 1 :(得分:1)
当按下“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键会导致焦点偏离它而不插入制表符。
答案 2 :(得分:1)
您可以在主JFrame
或JPanel
构造函数中调用以下方法。
通过调用方式使用: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) {}
});
}
}
答案 3 :(得分:0)
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 */