Question

I can't figure out a way to resize some components in a swing GUI. Some custom labels are being added to a FlowLayout which doesn't behave how they should when resizing the dialog. The panel is being built using the jgoodies forms framework.

If using this, where the FlowLayout is being added to xy(3, y)

FormLayout layout = new FormLayout("r:d, 5px, f:d:g", // columns
            "p, p, 5px, p, 5px, p") // rows

The FlowLayout expands and a scroll bar shows up
tags_scroll

If using

FormLayout layout = new FormLayout("r:d, 5px, f:10:g", // columns
            "p, p, 5px, p, 5px, p") // rows

The FlowLayout uses the available space and the items on the second line disappear
tags_vanish

I'd like to expand the height of each row containing a FlowLayout to the current height of the component. Unfortunately the preferred size always corresponds to the hight for a single row.
Would another layout be more appropriate? The bold text on the left should be aligned right, followed by the FlowLayout.

Sources

[edit] After having tried to figure out how to do this for weeks, the actual question can be resumed to this:
A set of labels is being added to a JPanel. This JPanel should use all available space horizontally (dialogue size minus width of tag name label) and expand as needed vertically. If the height of the JPanel gets bigger then the dialogue, a vertical scroll bar should show up (the horizontal scroll bar is never visible). The dialogue can show multiple JPanels which will be shown one after the other (vertically).

Here's an attempt using GridBagLayout and WrapLayout:

public class GridBagLayoutTagPanel extends JPanel {
private static final long serialVersionUID = -441746014057882848L;
private final int NB_TAGS = 5;

public GridBagLayoutTagPanel() {
    setLayout(new GridLayout());

    JPanel pTags = new JPanel(new GridBagLayout());
    pTags.setBackground(Color.ORANGE);
    GridBagConstraints c = new GridBagConstraints();
    c.ipadx = 5;
    c.ipady = 5;

    int rowIndex = 0;
    for (int i = 0; i < NB_TAGS; i++) {
        //add tag name
        JLabel lTagName = new JLabel(String.format("Tag %s:", i));
        lTagName.setFont(lTagName.getFont().deriveFont(Font.BOLD));
        c.fill = GridBagConstraints.NONE;
        c.gridx = 0;
        c.gridy = rowIndex++;
        pTags.add(lTagName, c);

        //add tag values
        JPanel pTag = new JPanel(new BorderLayout());
        pTag.add(new JLabel("+"), BorderLayout.LINE_START); //label used to add new tags
        pTag.add(getWrapPanel(), BorderLayout.CENTER); //the list of tag values
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 1;
        pTags.add(pTag, c);
    }

    //JScrollPane sp = new JScrollPane(pTags);
    //sp.setBorder(BorderFactory.createEmptyBorder());

    add(pTags);
    }

private static JPanel getWrapPanel() {
   JPanel p = new JPanel(new WrapLayout(FlowLayout.LEFT, 5, 0));

   for (int i = 0; i < 50; i++) {
           p.add(new JLabel("t" + i));
   }
   return p;
}

public static void main(String[] args) {
    JFrame f = new JFrame();
    f.getContentPane().add(new GridBagLayoutTagPanel());
    f.setSize(new Dimension(500, 300));
    f.setVisible(true);
}
}
Was it helpful?

Solution 2

With Rob's help and using his WrapPanel and ScrollablePanel it now works exactly as it should

public class GridBagLayoutTagPanel extends JPanel {
  private final int NB_TAGS = 5;
  private final int NB_TAGVALUES = 50;

  public GridBagLayoutTagPanel() {
    setLayout(new GridLayout());

    ScrollablePanel pTags = new ScrollablePanel(new GridBagLayout());
    pTags.setScrollableWidth(ScrollablePanel.ScrollableSizeHint.FIT);
    pTags.setBackground(Color.ORANGE);
    GridBagConstraints c = new GridBagConstraints();
    c.ipadx = 5;
    c.ipady = 5;

    int rowIndex = 0;
    for (int i = 0; i < NB_TAGS; i++) {
      // add tag name
      JLabel lTagName = new JLabel(String.format("Tag %s:", i));
      lTagName.setFont(lTagName.getFont().deriveFont(Font.BOLD));
      c.fill = GridBagConstraints.NONE;
      c.gridx = 0;
      c.gridy = rowIndex++;
      c.weightx = 0; // keep minimum size of the cell containing the label when resizing
      c.weighty = 0;
      pTags.add(lTagName, c);

      // add tag values
      JPanel pTag = new JPanel(new BorderLayout());
      pTag.add(new JLabel("+"), BorderLayout.LINE_START); // label used to add new tags
      pTag.add(getWrapPanel(), BorderLayout.CENTER); // the list of tag values
      c.fill = GridBagConstraints.HORIZONTAL;
      c.gridx = 1;
      c.weightx = 1; // fill horizontally
      c.weighty = 1;
      pTags.add(pTag, c);
   }

   JScrollPane sp = new JScrollPane(pTags);
   sp.setBorder(BorderFactory.createEmptyBorder());

   add(sp);
  }

  private JPanel getWrapPanel() {
    JPanel p = new JPanel(new WrapLayout(FlowLayout.LEFT, 5, 0));

    for (int i = 0; i < NB_TAGVALUES; i++) {
      p.add(new JLabel("t" + i));
    }

    p.setSize(400, 1);
    return p;
  }

  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.getContentPane().add(new GridBagLayoutTagPanel());
    f.setSize(new Dimension(500, 300));
    f.setVisible(true);
  }
}

OTHER TIPS

I'd like to expand the height of each row containing a FlowLayout to the current height of the component. Unfortunately the preferred size always corresponds to the hight for a single row.

Wrap Layout handles this.

Have you tried MigLayout? It's the only layout manager that I use, and I've never found a layout I couldn't get it to do.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top