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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5042429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 09:09:25  来源:igfitidea点击:

How can I modify the behavior of the tab key in a JTextArea?

javaswinguser-interfacewidget

提问by XGouchet

I'm creating a form in Java Swing, and one of the fields is a JTextArea. When I use the Tabkey on all other fields, it gives the focus to the next widget, but in the JTextArea, it inserts a tab character (horizontal space) in the text.

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

How can I modify this behavior?

如何修改此行为?

回答by camickr

/*
    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);
    }
}

回答by Bartzilla

you could use the "NextWidget.grabFocus()" method within keylistener of JTextArea when key "tab" is pressed

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

With this latter approach the tab character will still get inserted into the JTextArea before the focus is shifted away. If you dont want that behavior you can create a subclass of JTextArea whose isManagingFocus() method always returns false, instead of true. For example:

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

import javax.swing.*;

public class NoTabTextArea extends JTextArea {
    public boolean isManagingFocus() {
        return false;
    }
}

An instance of NoTabTextArea can be used exactly like a JTextArea, except that the tab key will cause the focus to shift away from it without a tab character being inserted.

NoTabTextArea 的实例可以像 JTextArea 一样使用,除了 Tab 键会导致焦点从它移开而不插入 Tab 字符。

回答by Abel M.

You can call the following method in your main JFrameor JPanelconstructor. Use by calling as so: disableTabbingInTextAreas(this)

您可以在 mainJFrameJPanel构造函数中调用以下方法。通过调用使用: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) {}
        });
    }
}

回答by Ashish

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 */