Question

I want to layout my JPane like so:

-------
|     |
|     |
|     |
-------
|     |
-------

This way, the top section is bigger/taller than the bottom section (the top section consists of another JPanel and uses the Graphics object to display an image, while the bottom section also consists of another JPanel but uses the Graphics object to draw some lines and text).

I've heard that the best way to do this was using the GridBagLayout and GridBagConstraints.

I'm trying to figure out the appropriate properties for the GridBagConstraints, and I'm having some difficulties. This is what I have so far...

For the top part, I have:

gridx = 0
gridy = 0
weighty = 1.0; // expand downwards, because the bottom should never expand in the Y direction
fill = GridBagConstraints.BOTH

For the bottom part, I have:

gridx = 0
gridy = 1
fill = GridBagConstraints.HORIZONTAL
anchor = GridBagConstraints.PAGE_END

Unfortunately, all the ends up happening is a large gray rectangle appears (I have a white background for the application) - no images load, no lines/text appear.

What should I do? What should I adjust?

I've read a few tutorials, but it just seems really confusing, I got it working in my first application, but now when I try to do this it just doesn't seem to work for me.

Was it helpful?

Solution

In general, for gridbag layout

  • if you want a component scale, you must give its scale direction a weight, and any sizes (width/height) you set for that direction will be ignored by the layout manager.

  • If you don't want a component scale, the component must have its size defined (if you want, you can dig into this topic in documents of java). In your case of the bottom panel, you need to give its, at least, a preferred height.

This can work as your expectation

pnlTop.setBackground(Color.WHITE);
pnlBottom.setBackground(Color.BLUE);

// Because you don't want the bottom panel scale, you need to give it a height.
// Because you want the bottom panel scale x, you can give it any width as the
// layout manager will ignore it.
pnlBottom.setPreferredSize(new Dimension(1, 20));


getContentPane().setLayout(new GridBagLayout());
GridBagConstraints cst = new GridBagConstraints();
cst.fill = GridBagConstraints.BOTH;
cst.gridx = 0;
cst.gridy = 0;
cst.weightx = 1.0; // --> You miss this for the top panel
cst.weighty = 1.0;
getContentPane().add(pnlTop, cst);

cst = new GridBagConstraints();
cst.fill = GridBagConstraints.HORIZONTAL;
cst.gridx = 0;
cst.gridy = 1;
cst.weightx = 1.0; // You miss this for the bottom panel
cst.weighty = 0.0;
getContentPane().add(pnlBottom, cst);

Further more, if you want to use gridbag layout, I recommend you to try the painless-gridbag library http://code.google.com/p/painless-gridbag/ (I'm the author of that library). It doesn't solve this problem for you (as your problem concerns managing component's size in gridbag layout) but it will save you a lot of typing and make your code easier to maintain

pnlBottom.setPreferredSize(new Dimension(1, 20));

PainlessGridBag gbl = new PainlessGridBag(getContentPane(), false);
gbl.row().cell(pnlTop).fillXY();
gbl.row().cell(pnlBottom).fillX();
gbl.done();

OTHER TIPS

not sure from your question, maybe will help you Top at 70%, Bottom at 30%

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

public class BorderPanels extends JFrame {

    private static final long serialVersionUID = 1L;

    public BorderPanels() {
        getContentPane().setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        JPanel panel1 = new JPanel();
        Border eBorder = BorderFactory.createEtchedBorder();
        panel1.setBorder(BorderFactory.createTitledBorder(eBorder, "70pct"));
        gbc.gridx = gbc.gridy = 0;
        gbc.gridwidth = gbc.gridheight = 1;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.weightx = gbc.weighty = 70;
        getContentPane().add(panel1, gbc);
        JPanel panel2 = new JPanel();
        panel2.setBorder(BorderFactory.createTitledBorder(eBorder, "30pct"));
        gbc.gridy = 1;
        gbc.weightx = 30;
        gbc.weighty = 30;
        gbc.insets = new Insets(2, 2, 2, 2);
        getContentPane().add(panel2, gbc);
        pack();
    }

    public static void main(String[] args) {
        new BorderPanels().setVisible(true);
    }
}

If you may use 3th party libs, you may consider the FormLayout as well. It allows you to specify the height of each row, and the resize behavior.

I did not test this but

FormLayout layout = new FormLayout( 
 "pref", //columns
 "50dlu:grow(0.2)","25dlu:grow(0.1)" //rows
);

might do the trick. More information on the syntax can be found in the JGoodies Forms pdf

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