Search code examples
javaswingjtextareakeylistener

Selecting text in JTextArea does not show any selection color


I have this piece of code in which a JTextArea is added to a JFrame. Whenever the user presses the key the content of the JTextArea should be selected.

Here is the code

import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;

public class SelectionTest extends KeyAdapter
{
    final JTextArea jTextArea;
    public static void main(String[] args)
    {
        new SelectionTest();
    }

    SelectionTest()
    {
        JFrame jFrame=new JFrame();
        jFrame.setLocationRelativeTo(null);
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jTextArea = new JTextArea("Test 1-2-3");
        jTextArea.addKeyListener(this);
        jFrame.add(jTextArea);
        jFrame.pack();
        jFrame.setVisible(true);
    }

    @Override
    public void keyPressed(KeyEvent e)
    {
        if( e.getKeyCode() != KeyEvent.VK_UP ) return;
        jTextArea.selectAll();
    }
}

However I observe that nothing is selected on pressing key, instead if I slightly change the method keyPressed to the following, it works.

@Override
public void keyPressed(KeyEvent e)
{
    if( e.getKeyCode() != KeyEvent.VK_UP ) return;
    SwingUtilities.invokeLater(new Runnable()
    {
        @Override
        public void run()
        {
            jTextArea.selectAll();
        }
    });
}

I want to know reason for this behaviour. Is it a threading issue ?


Solution

  • JTextArea uses arrow keys for moving the caret. You're probably interfering with it. That is why invokeLater() helps.

    Also, you have to make sure the component is focusable and has focus. Key listener is a lower level interface. As already mention above in the comments, it is better to use Key Bindings instead. See How to Use Key Bindings for details and examples.

    Here is an example based on the posted code that uses key bindings :

    import javax.swing.*;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyAdapter;
    
    public class SelectionTest extends KeyAdapter
    {
        final JTextArea jTextArea;
        public static void main(String[] args)
        {
            new SelectionTest();
        }
    
        SelectionTest()
        {
            JFrame jFrame=new JFrame();
            jFrame.setLocationRelativeTo(null);
            jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            jTextArea = new JTextArea("Test 1-2-3");
    
            Action someAction = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    jTextArea.selectAll();
                }
            };
            jTextArea.getInputMap().put(
                    KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "someAction");
            jTextArea.getActionMap().put("someAction", someAction);
            
            jFrame.add(jTextArea);
            jFrame.pack();
            jFrame.setVisible(true);
        }
    }
    

    Also note that if text area looses its focus it may not show the selection. So you may need to add jTextArea.requestFocusInWindow() before altering selection. Also there selectAll() that you may use to select all the text. See bug 4320295 : select and selectAll don't work on JTextArea for some details.