title: Dynamically change size of text box JTextArea
body: <p>I'm new to Java and I've been trying to build a simple instant messaging program. I would like the text box (the place where you type your messages before sending them) to dynamically change size (w/ a max height constraint) as a person enters in a large message, kinda like what happens on WhatsApp or iMessage.</p>
  
  <p>I've tried to count the number of lines of text that are in the text box (taking into account the effects of text wrapping), and then increase/decrease the text box's height according to the number of text-wrapped lines present. I determined the height of 1 row of text using the getScrollableUnitIncrement() method.</p>
  
  <p>Also, as I am learning, is there a better method of dynamically changing the size of the text box than the one I've outlined above?</p>
  
  <p>I used a JTextArea embedded in a JScrollPane and I'm using a componentListener on the JTextArea to resize the textbox as appropriate.</p>
  
  <p><strong>Please check out the while loops in the component listener method as I don't think this part of program works properly...</strong></p>
  
  <p>Here's a snippet of the code:</p>
  
  <pre><code>public class clienterrors extends JFrame {
      private JTextArea userText;
      private JTextPane chatWindow;
      private String userName="testName";
      private Document doc;
  
      // Automatic resizing of the text box
      private static Dimension textBoxSize = new Dimension(20, 20);
      public static int numRows = 1;
      private static final int rowHeight = 20;
      private final int maxHeight = 80;
  
  
      public static void main(String[] args) {
          clienterrors george = new clienterrors();
          george.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
      }
  
      public clienterrors(){
          super("Client instant messaging platform");
  
          // Chat window initialisation
          chatWindow = new JTextPane();
          chatWindow.setEditable(false);
          doc = chatWindow.getDocument();
          add(new JScrollPane(chatWindow), BorderLayout.CENTER);
  
  
          // Text box initialisation
          userText = new JTextArea();
          userText.setLineWrap(true);
          userText.setWrapStyleWord(true);
  
          JScrollPane jsp = new JScrollPane(userText);
          jsp.setPreferredSize(textBoxSize);
          jsp.setMaximumSize(new Dimension(20, 40));
  
  
          // Gets the text box to resize as appropriate
          userText.addComponentListener(
                  new ComponentAdapter() {
                      @Override
                      public void componentResized(ComponentEvent e) {
  
                          // Needs to cater for when removing &amp; pasting large messages into the text box
                          while (countLines(userText) &gt; numRows &amp;&amp; textBoxSize.getHeight() &lt; maxHeight) {
                              textBoxSize.setSize(20, (int) textBoxSize.getHeight() + rowHeight);
                              revalidate();
                              numRows++;  // numRows is used as an update to see which
                          }
  
                          while (countLines(userText) &lt; numRows &amp;&amp; textBoxSize.getHeight() &gt; 20){
                              textBoxSize.setSize(20, (int)textBoxSize.getHeight() - rowHeight);
                              revalidate();
                              numRows--;
                          }
                      }
                  }
          );
  
          // Allows u to send text from text box to chat window
          userText.addKeyListener(
                  new KeyAdapter() {
                      @Override
                      public void keyTyped(KeyEvent e) {
                          if(e.getKeyChar() == '\n' &amp;&amp; enterChecker(userText.getText())){
                              // returns the text (-1 on the substring to remove the \n escape character when pressing enter)
                              showMessage("\n" + userName + ": " + userText.getText().substring(0, userText.getText().length() - 1));
                              userText.setText("");
                          }
                      }
                  }
          );
          add(jsp, BorderLayout.SOUTH);
  
  
          //JFrame properties
          setSize(300, 400);
          setVisible(true);
      }
  
      // shows message on the chat window
      private void showMessage(final String text){
          SwingUtilities.invokeLater(
                  new Runnable() {
                      @Override
                      public void run() {
                          try{
                              doc.insertString(doc.getLength(), text, null);
                          }catch(BadLocationException badLocationException){
                              badLocationException.printStackTrace();
                          }
                          // place caret at the end (with no selection), so the newest message can be automatically seen by the user
                          chatWindow.setCaretPosition(chatWindow.getDocument().getLength());
                      }
                  }
          );
      }
  
      // Prevents the user from sending empty messages that only contain whitespace or \n
      private static boolean enterChecker(String t){
          for(int i=0; i&lt;t.length(); i++)
              if (t.charAt(i) != '\n' &amp;&amp; t.charAt(i) != ' ')
                  return true;
          return false;
      }
  
      // This counts the number of wrapped lines in the text box to compare to numRows - only used to resize the text box
      // (got this off the internet)
      private static int countLines(JTextArea textArea) {
          if(!enterChecker(textArea.getText())) return 0; // this prevents getting an error when you're sending an empty message
          AttributedString text = new AttributedString(textArea.getText());
          FontRenderContext frc = textArea.getFontMetrics(textArea.getFont())
                  .getFontRenderContext();
          AttributedCharacterIterator charIt = text.getIterator();
          LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc);
          float formatWidth = (float) textArea.getSize().width;
          lineMeasurer.setPosition(charIt.getBeginIndex());
  
          int noLines = 0;
          while (lineMeasurer.getPosition() &lt; charIt.getEndIndex()) {
              lineMeasurer.nextLayout(formatWidth);
              noLines++;
          }
  
          return noLines;
      }
  
  }
  </code></pre>