Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Word Wrap JLabel + JScrollPane problem.

843806Feb 4 2008 — edited Feb 7 2008
Greetings

I'm trying to display some information in a JLabel that has been nested within some JLabels and ultimately answer to a JScrollPane.

I've done the JLabel trick of using <HTML> in the label text to force word wrap but when I put everything inside a JScrollPane (to get a vertical scrollbar when needed) the labels PreferredSize goes to 6000+ pixels and runs off the edge.

I've attached some demo code. Compile, click the "Collect" button to see the behavior. Click "Dispose" to exit the App. I have it inputting some sample text. If you extend the app to the right, you'll notice more of the text is visible. I would like it word wrap and set its height appropriately.

To summarize my design methodology -

I wanted rows - a right justified checkbox, with a variable length label to the left. In order to accomplish this I put the label, some horizontal glue and the checkbox in a BoxLayout in a JPanel. (One nesting level.)

I created 6 rows and dropped them all in JPanel using SpringLayout and createCompactGrid from SpringUtilities.java (Two nesting levels.)

The third and final nesting level is to take that JPanel and drop it in the JScrollPane.

Everything I've read says this SHOULD work yet it doesn't.

I'd be grateful for a bit of insight.

Thanks!

Demo.java
////////////////////////////////////////////////////////////////////
// Demo.java
// v 0.1 Initial write
////////////////////////////////////////////////////////////////////

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.URL;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;


public class Demo extends javax.swing.JDialog implements
    ActionListener
{
  private static final long serialVersionUID = -1972440997220256547L;
  private JPanel contentPane;
  private JButton discardButton;
  private JTextField sourceTextField;
  private JPanel collectPane;
  private JPanel browsePane;
  private JLabel sourceLabel;
  private JPanel buttonPane;
  private JPanel sourcePane;
  private JPanel fieldPane;
  private JPanel pane1;
  private JPanel pane2;
  private JPanel pane3;
  private JPanel pane4;
  private JPanel pane5;
  private JPanel pane6;
  private JScrollPane fieldScrollPane;
  private JButton collectButton;
  private JPanel urlPane;
  private JButton browseButton;
  private JButton acceptButton;
  private String rssFilePath = "";
  private JCheckBox contentLinkCheckbox;
  private JLabel contentLinkLabel;
  private JCheckBox contentDateCheckbox;
  private JLabel contentDateLabel;
  private JCheckBox contentDescriptionCheckbox;
  private JLabel contentDescriptionLabel;
  private JCheckBox contentTitleCheckbox;
  private JLabel contentTitleLabel;
  private JCheckBox feedDescriptionCheckbox;
  private JLabel feedDescriptionLabel;
  private JCheckBox feedTitleCheckbox;
  private JLabel feedTitleLabel;

  /**
   * Auto-generated main method to display this JDialog
   */
  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        JFrame frame = new JFrame();
        Demo inst = new Demo(frame);
        inst.setVisible(true);
      }
    });
  }

  public Demo(JFrame frame)
  {
    super(frame);
    initGUI();
    getRootPane().setDefaultButton(collectButton);
  }

  private void initGUI()
  {
    try
    {
      setTitle("Demo");
      {
        sourcePane = new JPanel();
        fieldPane = new JPanel();
        fieldScrollPane = new JScrollPane(fieldPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 

JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        buttonPane = new JPanel();
        getContentPane().add(sourcePane, BorderLayout.NORTH);
        getContentPane().add(fieldScrollPane, BorderLayout.CENTER);
        getContentPane().add(buttonPane, BorderLayout.SOUTH);
        fillSourcePane();
        fillFieldPane();
        fillButtonPane();
        pack();
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }

  private void fillSourcePane()
  {
    // URL Pane - Contains Source File/URL controls.
    urlPane = new JPanel();
    FlowLayout urlPaneLayout = new FlowLayout();
    urlPaneLayout.setAlignment(FlowLayout.LEFT);
    sourcePane.add(urlPane);
    urlPane.setLayout(urlPaneLayout);
    // Source Label - shows text "Source File or URL:"
    sourceLabel = new JLabel();
    urlPane.add(sourceLabel);
    sourceLabel.setText("Source File or URL:");
    // Source Text Field - Absolute file location, or URL.
    sourceTextField = new JTextField();
    urlPane.add(sourceTextField);
    sourceTextField.setColumns(40);
    sourceTextField.setText("File or URL");
    // Browse Panel - Contains browse controls.
    browsePane = new JPanel();
    FlowLayout browsePaneLayout = new FlowLayout();
    browsePaneLayout.setAlignment(FlowLayout.LEFT);
    sourcePane.add(browsePane);
    browsePane.setLayout(browsePaneLayout);
    // Browse Button - To browse the file system for an XML file to load.
    browseButton = new JButton();
    browsePane.add(browseButton);
    browseButton.setText(". . .");
    browseButton.addActionListener(this);
    browseButton.setActionCommand("BROWSE");
    // Collect Panel - Contains collect controls.
    collectPane = new JPanel();
    FlowLayout collectPaneLayout = new FlowLayout();
    collectPaneLayout.setAlignment(FlowLayout.RIGHT);
    sourcePane.add(collectPane);
    collectPane.setLayout(collectPaneLayout);
    // Collect Button - The execute button. Will populate the fieldPane with the
    // XML contents.
    collectButton = new JButton();
    collectPane.add(collectButton);
    collectButton.setText("Collect");
    collectButton.addActionListener(this);
    collectButton.setActionCommand("COLLECT");
    // Layout for the source pane.
    BoxLayout sourcePaneLayout = new BoxLayout(sourcePane, BoxLayout.Y_AXIS);
    sourcePane.setLayout(sourcePaneLayout);
  }
  private void fillFieldPane()
  {
    fieldPane.setLayout(new SpringLayout());
    
    pane1 = new JPanel();
    pane2 = new JPanel();
    pane3 = new JPanel();
    pane4 = new JPanel();
    pane5 = new JPanel();
    pane6 = new JPanel();
    
    pane1.setLayout(new BoxLayout(pane1, BoxLayout.X_AXIS));
    pane2.setLayout(new BoxLayout(pane2, BoxLayout.X_AXIS));
    pane3.setLayout(new BoxLayout(pane3, BoxLayout.X_AXIS));
    pane4.setLayout(new BoxLayout(pane4, BoxLayout.X_AXIS));
    pane5.setLayout(new BoxLayout(pane5, BoxLayout.X_AXIS));
    pane6.setLayout(new BoxLayout(pane6, BoxLayout.X_AXIS));
    
    fieldPane.add(pane1);
    fieldPane.add(pane2);
    fieldPane.add(pane3);
    fieldPane.add(pane4);
    fieldPane.add(pane5);
    fieldPane.add(pane6);
    
    feedTitleLabel = new JLabel();
    feedTitleLabel.setText("Feed Title:");
    pane1.add(feedTitleLabel);
    pane1.add(Box.createHorizontalGlue());
    
    feedDescriptionLabel = new JLabel();
    feedDescriptionLabel.setText("Feed Description:");
    pane2.add(feedDescriptionLabel);
    pane2.add(Box.createHorizontalGlue());
    
    contentTitleLabel = new JLabel();
    contentTitleLabel.setText("Content Title:");
    pane3.add(contentTitleLabel);
    pane3.add(Box.createHorizontalGlue());
    
    contentDescriptionLabel = new JLabel();
    contentDescriptionLabel.setText("Content Description");
    pane4.add(contentDescriptionLabel);
    pane4.add(Box.createHorizontalGlue());
    
    contentDateLabel = new JLabel();
    contentDateLabel.setText("Content Date");
    pane5.add(contentDateLabel);
    pane5.add(Box.createHorizontalGlue());
    
    contentLinkLabel = new JLabel();
    contentLinkLabel.setText("ContentLink");
    pane6.add(contentLinkLabel);
    pane6.add(Box.createHorizontalGlue());

    feedTitleCheckbox = new JCheckBox();
    feedTitleCheckbox.setToolTipText("Display feed title");
    pane1.add(feedTitleCheckbox);
    
    feedDescriptionCheckbox = new JCheckBox();
    feedDescriptionCheckbox.setToolTipText("Display feed description");
    pane2.add(feedDescriptionCheckbox);
    
    contentTitleCheckbox = new JCheckBox();
    contentTitleCheckbox.setToolTipText("Display content title");
    pane3.add(contentTitleCheckbox);
    
    contentDescriptionCheckbox = new JCheckBox();
    contentDescriptionCheckbox.setToolTipText("Display content description");
    pane4.add(contentDescriptionCheckbox);
    
    contentDateCheckbox = new JCheckBox();
    contentDateCheckbox.setToolTipText("Display content date");
    pane5.add(contentDateCheckbox);

    contentLinkCheckbox = new JCheckBox();
    contentLinkCheckbox.setToolTipText("Display content link");
    pane6.add(contentLinkCheckbox);
    
    SpringUtilities.makeCompactGrid(fieldPane, 6, 1, 0, 0, 0, 0);
  }
  private void fillButtonPane()
  {
    // Accept Button - Accepts the changes, saves, and closes the window.
    acceptButton = new JButton();
    buttonPane.add(acceptButton);
    acceptButton.setText("Accept");
    acceptButton.addActionListener(this);
    acceptButton.setActionCommand("ACCEPT");
    // Discard Button - Discards changes, closes the window.
    discardButton = new JButton();
    buttonPane.add(discardButton);
    discardButton.setText("Discard");
    discardButton.addActionListener(this);
    discardButton.setActionCommand("DISCARD");
  }

  @Override
  public void actionPerformed(ActionEvent ae)
  {
    if (ae.getActionCommand().equals("BROWSE"))
    {
      // Browse the file system for a valid xml file.
      JFileChooser chooser = new JFileChooser();
      int retVal = chooser.showOpenDialog(this);
      if (retVal == JFileChooser.APPROVE_OPTION)
      {
        sourceTextField.setText(chooser.getSelectedFile().toString());
        rssFilePath = chooser.getSelectedFile().toString();
      }
    }
    else if (ae.getActionCommand().equals("COLLECT"))
    {
      contentDescriptionLabel.setText("Ponca City, We Love You writes 'There will be a 

program on applied physics and real time strategy that you might want to watch on television 

today. Conservation of momentum during elastic and inelastic collisions is one aspect on 

which to focus as players tackle their opponents. It is of critical importance that the 

Patriots bring down New York's huge and powerful running back, 6-foot-4, 265-pound Brandon 

Jacobs. An average-size NFL defensive back's mass combined with his speed � on average, 4.56 

seconds for the 40-yard dash � can produce up to 1600 pounds of tackling force. A tackle 

with half a ton of force may sound like a crippling blow, but the body can handle twice that 

amount because the player's equipment spreads out the incoming energy, lessening its 

severity.' Nanotech specialists from Cornell have developed their own take on the 'physics' 

of the Super Bowl by creating the world's smallest trophy, which will be awarded today to a 

contestant who best explains an aspect of football physics. Just some food for thought while 

you watch the game on your brand new HD television, though you'd better not be watching it 

in a church.");
    }
    else if (ae.getActionCommand().equals("ACCEPT"))
    {
      // Save and close
      dispose();
    }
    else if (ae.getActionCommand().equals("DISCARD"))
    {
      // Close the window
      dispose();
      System.exit(0);
    }
  }
}
SpringUtilities.java
import javax.swing.*;
import javax.swing.SpringLayout;
import java.awt.*;

/**
 * A 1.4 file that provides utility methods for
 * creating form- or grid-style layouts with SpringLayout.
 * These utilities are used by several programs, such as
 * SpringBox and SpringCompactGrid.
 */
public class SpringUtilities {
    /**
     * A debugging utility that prints to stdout the component's
     * minimum, preferred, and maximum sizes.
     */
    public static void printSizes(Component c) {
        System.out.println("minimumSize = " + c.getMinimumSize());
        System.out.println("preferredSize = " + c.getPreferredSize());
        System.out.println("maximumSize = " + c.getMaximumSize());
    }

    /**
     * Aligns the first <code>rows</code> * <code>cols</code>
     * components of <code>parent</code> in
     * a grid. Each component is as big as the maximum
     * preferred width and height of the components.
     * The parent is made just big enough to fit them all.
     *
     * @param rows number of rows
     * @param cols number of columns
     * @param initialX x location to start the grid at
     * @param initialY y location to start the grid at
     * @param xPad x padding between cells
     * @param yPad y padding between cells
     */
    public static void makeGrid(Container parent,
                                int rows, int cols,
                                int initialX, int initialY,
                                int xPad, int yPad) {
        SpringLayout layout;
        try {
            layout = (SpringLayout)parent.getLayout();
        } catch (ClassCastException exc) {
            System.err.println("The first argument to makeGrid must use SpringLayout.");
            return;
        }

        Spring xPadSpring = Spring.constant(xPad);
        Spring yPadSpring = Spring.constant(yPad);
        Spring initialXSpring = Spring.constant(initialX);
        Spring initialYSpring = Spring.constant(initialY);
        int max = rows * cols;

        //Calculate Springs that are the max of the width/height so that all
        //cells have the same size.
        Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)).
                                    getWidth();
        Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)).
                                    getWidth();
        for (int i = 1; i < max; i++) {
            SpringLayout.Constraints cons = layout.getConstraints(
                                            parent.getComponent(i));

            maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth());
            maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight());
        }

        //Apply the new width/height Spring. This forces all the
        //components to have the same size.
        for (int i = 0; i < max; i++) {
            SpringLayout.Constraints cons = layout.getConstraints(
                                            parent.getComponent(i));

            cons.setWidth(maxWidthSpring);
            cons.setHeight(maxHeightSpring);
        }

        //Then adjust the x/y constraints of all the cells so that they
        //are aligned in a grid.
        SpringLayout.Constraints lastCons = null;
        SpringLayout.Constraints lastRowCons = null;
        for (int i = 0; i < max; i++) {
            SpringLayout.Constraints cons = layout.getConstraints(
                                                 parent.getComponent(i));
            if (i % cols == 0) { //start of new row
                lastRowCons = lastCons;
                cons.setX(initialXSpring);
            } else { //x position depends on previous component
                cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST),
                                     xPadSpring));
            }

            if (i / cols == 0) { //first row
                cons.setY(initialYSpring);
            } else { //y position depends on previous row
                cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH),
                                     yPadSpring));
            }
            lastCons = cons;
        }

        //Set the parent's size.
        SpringLayout.Constraints pCons = layout.getConstraints(parent);
        pCons.setConstraint(SpringLayout.SOUTH,
                            Spring.sum(
                                Spring.constant(yPad),
                                lastCons.getConstraint(SpringLayout.SOUTH)));
        pCons.setConstraint(SpringLayout.EAST,
                            Spring.sum(
                                Spring.constant(xPad),
                                lastCons.getConstraint(SpringLayout.EAST)));
    }

    /* Used by makeCompactGrid. */
    private static SpringLayout.Constraints getConstraintsForCell(
                                                int row, int col,
                                                Container parent,
                                                int cols) {
        SpringLayout layout = (SpringLayout) parent.getLayout();
        Component c = parent.getComponent(row * cols + col);
        return layout.getConstraints(c);
    }

    /**
     * Aligns the first <code>rows</code> * <code>cols</code>
     * components of <code>parent</code> in
     * a grid. Each component in a column is as wide as the maximum
     * preferred width of the components in that column;
     * height is similarly determined for each row.
     * The parent is made just big enough to fit them all.
     *
     * @param rows number of rows
     * @param cols number of columns
     * @param initialX x location to start the grid at
     * @param initialY y location to start the grid at
     * @param xPad x padding between cells
     * @param yPad y padding between cells
     */
    public static void makeCompactGrid(Container parent,
                                       int rows, int cols,
                                       int initialX, int initialY,
                                       int xPad, int yPad) {
        SpringLayout layout;
        try {
            layout = (SpringLayout)parent.getLayout();
        } catch (ClassCastException exc) {
            System.err.println("The first argument to makeCompactGrid must use SpringLayout.");
            return;
        }

        //Align all cells in each column and make them the same width.
        Spring x = Spring.constant(initialX);
        for (int c = 0; c < cols; c++) {
            Spring width = Spring.constant(0);
            for (int r = 0; r < rows; r++) {
                width = Spring.max(width,
                                   getConstraintsForCell(r, c, parent, cols).
                                       getWidth());
            }
            for (int r = 0; r < rows; r++) {
                SpringLayout.Constraints constraints =
                        getConstraintsForCell(r, c, parent, cols);
                constraints.setX(x);
                constraints.setWidth(width);
            }
            x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad)));
        }

        //Align all cells in each row and make them the same height.
        Spring y = Spring.constant(initialY);
        for (int r = 0; r < rows; r++) {
            Spring height = Spring.constant(0);
            for (int c = 0; c < cols; c++) {
                height = Spring.max(height,
                                    getConstraintsForCell(r, c, parent, cols).
                                        getHeight());
            }
            for (int c = 0; c < cols; c++) {
                SpringLayout.Constraints constraints =
                        getConstraintsForCell(r, c, parent, cols);
                constraints.setY(y);
                constraints.setHeight(height);
            }
            y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad)));
        }

        //Set the parent's size.
        SpringLayout.Constraints pCons = layout.getConstraints(parent);
        pCons.setConstraint(SpringLayout.SOUTH, y);
        pCons.setConstraint(SpringLayout.EAST, x);
    }
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Mar 6 2008
Added on Feb 4 2008
8 comments
948 views