title: Text-like JPanel wrapping in Java Swing
body: <p>In short, I want to achieve this layout using swing:</p>
  
  <p><img src="https://i.stack.imgur.com/GyRrE.png" alt="enter image description here"></p>
  
  <p>Notice two main objectives:</p>
  
  <ul>
  <li><p>JPanels behaves as text, they are wrapped to <strong>width</strong> of a window,
  and in case of lack of space, they are wraped to next "lines" of
  JPanels.</p></li>
  <li><p>There is no horizontal scorll, but vertical scroll is present to
  privide access to view all possible elements in window.</p></li>
  </ul>
  
  <p><strong>Nick Rippe provided an almost done solution <a href="https://stackoverflow.com/a/13295450">below</a></strong>, it can be seen <a href="http://pastebin.com/MmGdf9nG" rel="nofollow noreferrer">here</a> as standalone java program with my updated more-random innermost textarea strings and left aligment. </p>
  
  <p>The last step is to fix each-row top alignment of textareas in CPanel:</p>
  
  <p><code>((WrapLayout)getLayout()).setAlignOnBaseline( true );</code></p>
  
  <p><strong>Complete solution:</strong></p>
  
  <pre><code>import java.awt.*;
  import java.awt.event.*;
  import javax.swing.*;
  import javax.swing.border.Border;
  
  public class APanel extends JScrollPane {
  
      int width = 0;
  
      public static String getRandomMultilineText() {
          String filler = "";
          int words = (int) (Math.random() * 7) + 1;
          for ( int w = 0 ; w &lt; words ; w++ ) {
              int lettersInWord = (int) (Math.random() * 12) + 1;
              for ( int l = 0 ; l &lt; lettersInWord ; l++ ) {
                  filler += "a";
              }
              filler += "\n";
          }
          return filler.trim();
      }
  
      public APanel() {
          super();
  
          setAlignmentX( LEFT_ALIGNMENT );
          setAlignmentY( TOP_ALIGNMENT );
  
          final Box B = Box.createVerticalBox();
          B.setAlignmentX( LEFT_ALIGNMENT );
          B.setAlignmentY( TOP_ALIGNMENT );
  
          for ( int i = 0 ; i &lt; 4 ; i++ ) {
              B.add( new CPanel() {
  
  
                  //Important!!! Make sure the width always fits the screen
                  public Dimension getPreferredSize() {
  
  
                      Dimension result = super.getPreferredSize();
                      result.width = width - 20; // 20 is for the scroll bar width
                      return result;
                  }
              } );
          }
  
          setViewportView( B );
  
          //Important!!! Need to invalidate the Scroll pane, othewise it
          //doesn't try to lay out when the container is shrunk
          addComponentListener( new ComponentAdapter() {
              public void componentResized( ComponentEvent ce ) {
                  width = getWidth();
                  B.invalidate();
              }
          } );
      }
  
      // nothing really very special in this class - mostly here for demonstration
      public static class CPanel extends JPanel {
  
          public CPanel() {
              super( new WrapLayout( WrapLayout.LEFT ) );
              ((WrapLayout)getLayout()).setAlignOnBaseline( true);
  
  
              setOpaque( true );
              setBackground( Color.gray );
              setAlignmentY( TOP_ALIGNMENT );
              setAlignmentX( LEFT_ALIGNMENT );
  
  
              int wordGroups = (int) (Math.random() * 14) + 7;
  
              //Adding test data (TextAreas)
              for ( int i = 0 ; i &lt; wordGroups ; i++ ) {
  
                  JTextArea ta = new JTextArea( getRandomMultilineText() );
                  ta.setAlignmentY( TOP_ALIGNMENT );
                  ta.setAlignmentX( LEFT_ALIGNMENT);
                  add( ta );
              }
              Border bx = BorderFactory.createTitledBorder( "Lovely container" );
  
              setBorder( bx );
          }
      }
  
      public static void main( String[] args ) {
          final JFrame frame = new JFrame();
          frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
          frame.add( new APanel() );
          frame.pack();
          frame.setSize( 400 , 300 );
          frame.setLocationRelativeTo( null );
          frame.setVisible( true );
      }
  }
  </code></pre>