Search code examples
javaswingjtextareakeylistenerkey-bindings

JTextArea pressing enter adds unnecessary new line


I'm developing a chat application and when I press an enter button when focusing the JTextArea I want it to stop adding the unnecessary new line of text, so for example i will be able to determine when user has pressed the enter button and not typed anything inside the JTextArea. I am using a KeyListener for the means of detecting when an user has released the enter key and then sending the message. I firstly tried replacing the new line of text with an empty string message.replaceAll("[\n]", "") and also trimming the message, however it didn't work. Is there anything i'm doing wrong with my approach or would there be any other solution i could adapt?


Solution

    • Don't use a JTextArea for this, but instead use a JTextField.
    • You can then easily listen for the enter press by giving the JTextField an ActionListener.
    • Most Swing chat applications I've seen use two text components for this: a JTextArea to display incoming text and your sent text, and a JTextField to allow user input of the text to send.
    • Usually one is right on top of the other using a BorderLayout.


    • If you absolutely must use a JTextArea, then you will probably want to use Key Binding to capture the enter key and deal with it. Check out the How to use Key Bindings Tutorial.


    For example:

    Example Key Bindings Solution:

    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class CaptureTextAreaEnter extends JPanel {
       private static final int COLS = 30;
       private static final int VIEW_ROWS = 12;
       private static final int ENTER_ROWS = 4;
       private JTextArea chatViewArea = new JTextArea(VIEW_ROWS, COLS);
       private JTextArea chatEnterArea = new JTextArea(ENTER_ROWS, COLS);
    
       public CaptureTextAreaEnter() {
          setLayout(new BorderLayout());
          add(new JScrollPane(chatViewArea), BorderLayout.CENTER);
          add(new JScrollPane(chatEnterArea), BorderLayout.SOUTH);
    
          chatViewArea.setFocusable(false);
    
          chatViewArea.setWrapStyleWord(true);
          chatEnterArea.setWrapStyleWord(true);
          chatViewArea.setLineWrap(true);
          chatEnterArea.setLineWrap(true);
    
          // start our set up of key bindings
    
          // to get the correct InputMap
          int condition = WHEN_FOCUSED;  
          // get our maps for binding from the chatEnterArea JTextArea
          InputMap inputMap = chatEnterArea.getInputMap(condition);
          ActionMap actionMap = chatEnterArea.getActionMap();
    
          // the key stroke we want to capture
          KeyStroke enterStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
    
          // tell input map that we are handling the enter key
          inputMap.put(enterStroke, enterStroke.toString());
    
          // tell action map just how we want to handle the enter key
          actionMap.put(enterStroke.toString(), new AbstractAction() {
    
             @Override
             public void actionPerformed(ActionEvent arg0) {
                String text = chatEnterArea.getText();
                chatEnterArea.setText("");
                chatViewArea.append(text + "\n");
    
                // *** you will want to send text to your 
                // *** PrintStream to the chat server here 
             }
          });
       }
    
       private static void createAndShowGui() {
          CaptureTextAreaEnter mainPanel = new CaptureTextAreaEnter();
    
          JFrame frame = new JFrame("CaptureTextAreaEnter");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }