1

I have the following class

public class Demo {

private JFrame mainFrame;

static public Color BGCOLOUR1 = new Color(240, 240, 240);

public Demo() {
    mainFrame = new JFrame("Demo");
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setLayout(new BorderLayout());
    mainFrame.setSize(900, 800);

    JPanel centralPanel = new JPanel();
    centralPanel.setOpaque(true);
    centralPanel.setBackground(BGCOLOUR1);
    centralPanel.setLayout(new GridBagLayout());
    centralPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20),
            BorderFactory.createTitledBorder("Panel")));

    JPanel insidePanel = new JPanel();
    insidePanel.setOpaque(true);
    insidePanel.setBackground(BGCOLOUR1);
    insidePanel.setLayout(new BorderLayout());
    insidePanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Inside panel"),
            BorderFactory.createEmptyBorder(10, 10, 10, 10)));


    JTextArea insidePanelText = new JTextArea(6, 50);
    insidePanelText.setLineWrap(true);

    insidePanel.add(insidePanelText);

    centralPanel.add(insidePanel, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTH,
            GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0));

    JScrollPane scrollPane = new JScrollPane(centralPanel);
    mainFrame.add(scrollPane);
}

Why is the inside panel positioned in the centre of the centralPanel (vertically) when I set the GridBagConstraints anchor to NORTH? I would like it positioned at the top.

Also, if I add the centralPanel in a JScrollPane before adding it to the mainFrame as per the example I can resize the application larger just fine, but as soon as I resize it smaller (even though it is still larger than I originally started it) a scroll bar appears. How can I prevent that from happening?

Edit: To illustrate the scrolling problem (I packed the frame when I took these screens):

The application when started

When I start the application it has no scrollbars

The application when made larger and then smaller again

I resize the window larger, and then smaller again. As soon as I make it smaller, the scrollbar appears.

Lieuwe
  • 1,734
  • 2
  • 27
  • 41
  • Use `pack` instead of `mainFrame.setSize(900, 800);` – MadProgrammer Apr 27 '16 at 10:43
  • No, I don't want the window to fit its contents. I want it to be the size I specify. – Lieuwe Apr 27 '16 at 10:45
  • `pack` will solve your second problem – MadProgrammer Apr 27 '16 at 10:45
  • Is there no other way? I have several `JPanel`s of different height that I am adding to the GridbagLayout dynamically below that inside panel (over a background image) If I `pack` the mainFrame it results in a window that resizes/adds a vertical scrollbar when that happens which I would rather avoid. – Lieuwe Apr 27 '16 at 10:56
  • I'm not sure I understand the particular problem (with the scroll bars). I wasn't able to replicate the issue you're describing – MadProgrammer Apr 27 '16 at 11:01
  • I added some screenshots to illustrate it – Lieuwe Apr 27 '16 at 11:13
  • 1
    I "think" this is a combination of issues, essentially, when you sized the window horizontally, the "preferred size" of the component basically becomes the available space and it doesn't want to give it up when you shrink it back. I'm not sure of a fix for this using `GridBagLayout` – MadProgrammer Apr 27 '16 at 11:24
  • Your thinking was right. Just before I set the frame to visible I get a copy of the preferredSize Dimension for that text area. I created a class that is derived from it and then override getPreferredSize() which returns that copy instead of the super.getPreferredSize() from then on. That fixes the 'problem' I was seeing. – Lieuwe May 10 '16 at 14:02

1 Answers1

2

As far as GridBagLayout is concerned, based on the properties you've supplied, it is been laid out to the NORTH of the cell.

GridBagLayout works mostly to the preferred size of the components and calculates the positions of each component around the center of the parent container.

If, instead of:

new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTH,
        GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)

I use something like:

new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTH,
        GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)

it will produce the desired result.

Basically, by using gridy and setting it to 1, we're asking GridBagLayout to give all the remaining vertical space to this cell, but because we're not filling the cell, the contents is pushed to the NORTH of the cell

Vertical position

Also, if I add the centralPanel in a JScrollPane before adding it to the mainFrame as per the example I can resize the application larger just fine, but as soon as I resize it smaller (even though it is still larger than I originally started it) a scroll bar appears. How can I prevent that from happening?

I couldn't really replicate this particular problem, I could use either pack or setSize and resized the window smaller to its "packed" size and the scroll bars would appear, but once I resized the window beyond the "packed" size the scroll bars would disappear

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks for the explanation. I don't want the inside panel to resize vertically if I add more panels below it which is why I had originally solved it by adding an empty 'stretcher' panel at the bottom row of the `GridBagLayout` which was the only element to have a `weighty` factor. This works, but I thought there would be a better way of doing this. – Lieuwe Apr 27 '16 at 11:04
  • Okay, normally what I do in this case is have a "filler" component which has the `weighty` set to `1` and which is pushed down each time you add another component. You can use [`GridBagLayout#getConstraints`](https://docs.oracle.com/javase/8/docs/api/java/awt/GridBagLayout.html#getConstraints-java.awt.Component-) to get a copy of the original constraints for the component and once you've updated them, you can use [`GridBagLayout#setConstraints`](https://docs.oracle.com/javase/8/docs/api/java/awt/GridBagLayout.html#setConstraints-java.awt.Component-java.awt.GridBagConstraints-) to reapply them – MadProgrammer Apr 27 '16 at 11:08
  • Of course if that's all too much, you could try using the `VerticalLayout` from SwingLab's SwingX library, [for example](http://stackoverflow.com/questions/19148603/resizable-layout-swing-when-disappears-jpanel/19149113#19149113) – MadProgrammer Apr 27 '16 at 11:09