2

When I set a border color to every item in a JPanel with GridBagLayout, the components collapse.

Collapsed

but when I remove the border off just one component, the padding stays as expected.

Normal

What am I doing wrong?

Border Setting:

    setBorder(BorderFactory.createLineBorder(Color.decode("#"+Constants.Display.OPTIONS_BORDER_COLOR)));

JPanel:

public class OptionsPanel extends JPanel {
    private AddMachineBtn addMachineBtn;
    private SearchField searchField;
    private SearchBtn searchBtn;

    private GridBagConstraints gbc;

    public OptionsPanel() {
        init();
        config();
        build();
    }

    private void init() {
        addMachineBtn = new AddMachineBtn("Add Machine");
        searchField = new SearchField("Search...");
        searchBtn = new SearchBtn("S");

        gbc = new GridBagConstraints();
        int i = Constants.Display.OPTIONS_PANEL_PADDING;
        gbc.insets = new Insets(i, i, i, i);
    }

    private void config() {
        setLayout(new GridBagLayout());
        setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.decode("#"+Constants.Display.OPTIONS_BORDER_COLOR)));
        setPreferredSize(new Dimension(0, Constants.Display.OPTIONS_PANEL_HEIGHT));
        gbc.gridy = 0;
        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.anchor = gbc.LINE_START;
    }

    private void build() {
        gbc.gridx = 0;
        add(addMachineBtn, gbc);

        gbc.weightx = 0;
        gbc.gridx = 1;
        add(searchField, gbc);

        gbc.gridx = 2;
        add(searchBtn, gbc);
    }
}
miken32
  • 42,008
  • 16
  • 111
  • 154
BinaryShrub
  • 346
  • 1
  • 3
  • 14
  • AFAICS, you setting sizes as well as you using a LayoutManager. Let `LayoutManager` take care of the size of each and every component. Don't add lines like `setPreferredSize(...)` explicitly inside your code, this thing belongs to the Layout concern. Let it take care of that. – nIcE cOw Aug 01 '12 at 18:23
  • 2
    @GagandeepBali This is Spart... er, this is `GridBagLayout`. Not only you have to set your `preferredSize`s for controls not to jump randomly about the screen, you have no guarantee the sizes set will be respected. The only response to `GridBagLayout` problems is: use http://www.miglayout.com if only your project allows that. Among other things, `MigLayout` is notorious for respecting preferred sizes where `GridBagLayout` is not. – pafau k. Aug 01 '12 at 18:48
  • 1
    @pafauk. : With due respect, `GridBagLayout` is all about setting sizes using `weightx/weighty` and not explicitly defining `setPreferredSize()`. Those two constraints are responsible for giving size related to what you want, not the other way around. Here is one [example](http://stackoverflow.com/a/11166903/1057230), using Constraints. – nIcE cOw Aug 01 '12 at 19:20
  • sePreferredSize works fine until adding setBorder. – BinaryShrub Aug 01 '12 at 20:38

4 Answers4

4

I'm not sure about how it affects GridBagLayout, but "In general, when you want to set a border on a standard Swing component other than JPanel or JLabel, we recommend that you put the component in a JPanel and set the border on the JPanel."—setBorder(). There's a related example here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • There must be a way to change the border on the component and not just by adding an additional border around the component. – BinaryShrub Aug 01 '12 at 20:39
  • @Nestor [explains](http://stackoverflow.com/a/11767263/230513) the underlying problem well. – trashgod Aug 01 '12 at 20:51
2

Yes, layout has no affect to components' size. You may try to change layout (for example to FlowLayout) but situation will be the same. Swing components obtains its border during initialization from Look'n'Feel.

Insert System.out.println(addMachineBtn.getBorder()); after addMachineBtn creation. You will see that the border already exists

javax.swing.plaf.BorderUIResource$CompoundBorderUIResource

This border provides its own insets for component, and when you replace border by another ones you loose its insets.

Nestor
  • 756
  • 4
  • 8
1

If it's really important to keep original components insets and replace border, try to imitate native Swing borders.

For example something like this:

addMachineBtn.setBorder(new CompoundBorder(new LineBorder(Color.red), new EmptyBorder(5, 17, 5, 17)));

Instead of LineBorder put border what you need, EmptyBorder keep the same, just correct insets as needed.

Nestor
  • 756
  • 4
  • 8
0

The fix to this was changing the following

setSize(new Dimension(w,h));
setMinimumSize(new Dimension(w,h));
setMaximumSize(new Dimension(w,h));

to

setPreferredSize(new Dimension(w,h));
setMinimumSize(new Dimension(w,h));
setMaximumSize(new Dimension(w,h));
BinaryShrub
  • 346
  • 1
  • 3
  • 14
  • Here's the [downside](http://stackoverflow.com/q/7229226/230513). One common anomaly is truncated/misaligned text on platforms having differing font metrics. – trashgod Aug 01 '12 at 20:48