karmapolice
karmapolice

Reputation: 336

BoxLayout ignores subpanel alignment

I have a JPanel with a BoxLayout manager that contains subpanels. I want the components inside these subpanels to have a left alignment, but they always appear centered. It looks like BoxLayout correctly aligns components that are inserted directly, but fails to do that when they are inside a subpanel.

I have modified the example found in http://www.java2s.com/Tutorial/Java/0240__Swing/YAxisAlignment.htm so each button is placed inside a subpanel, and then the subpanel is placed inside the main panel with the BoxLayout manager:

public class YAxisAlignX {
  private static Container makeIt(String title, float alignment) {
    String labels[] = { "--", "----", "--------", "------------" };

    JPanel container = new JPanel();
    container.setBorder(BorderFactory.createTitledBorder(title));
    BoxLayout layout = new BoxLayout(container, BoxLayout.Y_AXIS);
    container.setLayout(layout);

    // modified loop. the original version does not create JPanel pan.
    // adds the buttons directly the the JPanel container with the
    // BoxLayout
    for (int i = 0, n = labels.length; i < n; i++) {
      JPanel pan = new JPanel();
      JButton button = new JButton(labels[i]);
      pan.add(button);
      button.setAlignmentX(alignment);
      pan.setAlignmentX(alignment);
      container.add(pan);
    }
    return container;
  }

  public static void main(String args[]) {
    JFrame frame = new JFrame("Alignment Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Container panel1 = makeIt("Left", Component.LEFT_ALIGNMENT);
    Container panel2 = makeIt("Center", Component.CENTER_ALIGNMENT);
    Container panel3 = makeIt("Right", Component.RIGHT_ALIGNMENT);

    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new FlowLayout());
    contentPane.add(panel1);
    contentPane.add(panel2);
    contentPane.add(panel3);

    frame.pack();
    frame.setVisible(true);
  }
}

If you execute this version, you can see that the buttons are all centered, despite the alignment set. Why is this happening? Is there any solution? In my case, every subpanel contains several components, and I do not want to add then directly to the main panel.

Thank you very much.

Upvotes: 1

Views: 681

Answers (1)

DSquare
DSquare

Reputation: 2468

But they are aligned!

First of all, setAlignmentX changes a property at a JComponent level, the layout in which these components are placed may or may not use this information. For example, BoxLayout uses it but FlowLayout and BorderLayout don't.

In your case you are placing some panels with a vertical BoxLayout and you are aligning them in various ways, and it works! It just so happens that the the panels stretch themselves to fit the whole column so actually aligning doesn't change their appearance. You can see this by setting a Border around the panels:

pan.setBorder(BorderFactory.createLineBorder(Color.red));

See:

enter image description here

The fact that the panels contain a button or anything else is mostly irrelevant (it only influences the size that the panel wants to take, and not definitely), the BoxLayout is aligning panels not what is there inside the panels, that's the work of each panel's layout. That's why the buttons wouldn't have its alignment affected by the BoxLayout.

Now how are those buttons deciding its alignment? Well that's up to the layout they are in. The buttons are inside the pan panel that is using the default LayoutManager FlowLayout. Now, as I said, FlowLayout doesn't care for the alignmentX/Y property so the line:

button.setAlignmentX(alignment);

Doesn't accomplish anything. To align in a FlowLayout you need to change its alignment field through FlowLayout.setAligment(int) (docs), you can also do this in the constructor, so If we change the pan declaration to:

JPanel pan = new JPanel(new FlowLayout(FlowLayout.LEFT));

You'll also have the buttons aligned to the left inside their panels:

//img

Of course, all the columns are aligned to the left since the parameter float alignment of makeIt does not influence the FlowLayout's alignment just the BoxLayout's one (and it doesn't matter). You might want to change that argument to an int and call the function with the different FlowLayout constants.

All in all, in the original version the line button.setAlignmentX(alignment); made sense because the buttons were added directly to the container panel and the BoxLayout aligned them properly:

enter image description here

However once you put the buttons inside other panels, the BoxLayout starts aligning the panels (which because of how panels works inside a BoxLayout they were being stretched to fill the whole width) not the buttons, and the buttons alignment is up to the panels layout. That's how it has to work so we can make consistent nested layouts.

I hope that's clear.

Upvotes: 2

Related Questions