Detailed GridBagLayout tutorial

D

Deniz Dogan

Hello!

I'm trying to learn how to use a GridBagLayout in my small project but I
can't seem to find a decent and detailed tutorial on the subject. There
are very many parameters in a GridBagConstraints constructor and I
suppose I need to know what each of the parameters do, to avoid simply
cutting-and-pasting different examples until I get it the way I want it.

If someone is interested, I'm looking to make the following:
A JTable covering the frame 100% horizontally and about 70% vertically,
located at the very top of the frame.
Just below the JTable I will have a small JPanel that will cover 100% of
the horizontal size and 10% vertically.
Just below that JPanel I will have yet another JPanel covering the rest
of the frame.

/Deniz Dogan
 
T

Thomas Weidenfeller

Deniz said:
I'm trying to learn how to use a GridBagLayout in my small project but I
can't seem to find a decent and detailed tutorial on the subject.

A small one is in

http://java.sun.com/docs/books/tutorial/uiswing/layout/gridbag.html

Details are in the int API documentation of gbl and gbc. Writing a few
own examples and playing with them also helps.
There
are very many parameters in a GridBagConstraints constructor and I
suppose I need to know what each of the parameters do,

Yes, you need. Or you at least you need to know where to look up details
(in the documentation).
If someone is interested, I'm looking to make the following:

Take out a piece of paper and a pencil. Sketch you gui. Superimpose
(read: draw on top :)) the grid cells you want to use. For each cell,
go through the gbl/gbc documentation and note down each cell's
configuration (gridx, gridy, weightx, weighty, fill, ...). Mark the
anchor points in your drawing, sort out the filling properties (depends
on component type), think through how resizing will look with your
parameters on paper, etc. Implement that configuration. If things don't
work as expected, go back to your paper and check the data, then check
your implementation.

Once you have a working GUI, do it all from scratch again, this time
taking the spacing information from

http://java.sun.com/products/jlf/ed2/book/HIG.Visual2.html

into account. Please note that when they talk about "Grid" in that book,
they don't suggest that you model each spacing with on own GridBagLayout
cell. Instead you have to apply insets (or padding) in creative ways to
your existing cells. Note: try to stick with one, insets (external
component padding) or internal component padding (ipadx, ipady), but
avoid confusion by using both. Insets are more flexible.


/Thomas

PS: After you have done it a few time, start looking for a GUI editor
which suits your needs. They all have big drawbacks. Look for the one
with the drawbacks that affect you least.
 
D

Deniz Dogan

Thomas Weidenfeller wrote:
[snippetysnip]

Thank you, Thomas. I've read it through and I've figured some of it out.
However, I can't get it to do exactly what I want it to. Also, my
question was wrong, here's the "real" question:

Consider three panels, panel_up, panel_middle, panel_bottom.
panel_bottom should have a fix height of 100 pixels. panel_middle should
also have a fix height of 50 pixels. panel_up should take up all of the
space left of the JFrame that everything is put on. How do I go about
doing that?

Some sweet ASCII art showing my problem:

JFrame
---------------------
| |
| panel_up | dynamic height: GridBagLayout.REMAINDER
| |
| |
|---------------------|
| panel_middle | fix height: 50 px
|---------------------|
| panel_bottom | fix height: 100 px
| |
---------------------


Thanks in advance.

/Deniz Dogan
 
A

A. Bolmarcich

Hello!

I'm trying to learn how to use a GridBagLayout in my small project but I
can't seem to find a decent and detailed tutorial on the subject. There
are very many parameters in a GridBagConstraints constructor and I
suppose I need to know what each of the parameters do, to avoid simply
cutting-and-pasting different examples until I get it the way I want it.

If someone is interested, I'm looking to make the following:
A JTable covering the frame 100% horizontally and about 70% vertically,
located at the very top of the frame.
Just below the JTable I will have a small JPanel that will cover 100% of
the horizontal size and 10% vertically.
Just below that JPanel I will have yet another JPanel covering the rest
of the frame.

GridBagLayout does not support allocating percentages of the container
size among the components in the container. You can get that effect
using GridBagLayout by also overriding the preferred and minimum sizes
of the components. However, it would be better to use a layout manager
that supports the type of layout that you want, such as TableLayout (see
http://java.sun.com/products/jfc/tsc/articles/tablelayout/index.html).
 
K

Knute Johnson

A. Bolmarcich said:
GridBagLayout does not support allocating percentages of the container
size among the components in the container. You can get that effect
using GridBagLayout by also overriding the preferred and minimum sizes
of the components. However, it would be better to use a layout manager
that supports the type of layout that you want, such as TableLayout (see
http://java.sun.com/products/jfc/tsc/articles/tablelayout/index.html).

That's just not true. GBL is great for just that type of layout.

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

public class test extends JFrame {
public test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setLayout(new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;

c.weightx = .7;
JButton b = new JButton("70%");
add(b,c);

c.weightx = .3;
b = new JButton("30%");
add(b,c);

setSize(400,300);
setVisible(true);
}

public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
new test();
}
};
EventQueue.invokeLater(r);
}
}
 
A

A. Bolmarcich

That's just not true. GBL is great for just that type of layout.

What I wrote is true. In the example program, the "70%" button is
allocated 70% of the extra width, not 70% of the width of the container.
The extra width is the difference between the width of the container
and the sum of the preferred (or minimum) widths of the two buttons.

When I compile and run the program (after changing the invocation of the
setLayout and add methods to invoke on the content pane of the JFrame
rather than the JFrame) the width of "70%" button is 248 and the width
of the "30%" button is 140. Which is a 64%/36% distribution of the
width, not 70%/30%.

If setSize(400,300) is replaced with pack(), then the width of each
button is 59. Which is a 50%/50% distribution of the width, not
70%/30%.

If the ratios of the preferred and minimum widths of the two buttons
is 70%/30%, then having GridBagLayout distribute 70% of the extra
space to the larger button and 30% of the extra space to the smaller
button will keep the widths of the components in the 70%/30% ratio.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test extends JFrame {
public test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setLayout(new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;

c.weightx = .7;
JButton b = new JButton("70%");
add(b,c);

c.weightx = .3;
b = new JButton("30%");
add(b,c);

setSize(400,300);
setVisible(true);
}

public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
new test();
}
};
EventQueue.invokeLater(r);
}
}
 
K

Knute Johnson

A. Bolmarcich said:
What I wrote is true. In the example program, the "70%" button is
allocated 70% of the extra width, not 70% of the width of the container.
The extra width is the difference between the width of the container
and the sum of the preferred (or minimum) widths of the two buttons.

When I compile and run the program (after changing the invocation of the
setLayout and add methods to invoke on the content pane of the JFrame
rather than the JFrame)

As of 1.5 JFrame.add() is the same as JFrame.getContentPane().add()

the width of "70%" button is 248 and the width
of the "30%" button is 140. Which is a 64%/36% distribution of the
width, not 70%/30%.

Looks pretty close to me.
If setSize(400,300) is replaced with pack(), then the width of each
button is 59. Which is a 50%/50% distribution of the width, not
70%/30%.

If the ratios of the preferred and minimum widths of the two buttons
is 70%/30%, then having GridBagLayout distribute 70% of the extra
space to the larger button and 30% of the extra space to the smaller
button will keep the widths of the components in the 70%/30% ratio.

If the components are at their minimum sizes they will probably be the
same size.

TableLayout looks nice but it isn't part of Sun's API. I try not to use
things like that because they go out of date or are no longer supported
or whatever. If you stick to what comes with the API you can do what
the OP wanted, to a reasonable degree, and that's all you usually get
out of a layout manager any way.

The one thing I see that he is going to have a problem with is that
JTables don't appear to resize vertically.

The easiest solution is to not use a layout manager. I know that that
sends shudders through the cognoscenti but there are millions of C
programs out there that position their components that way.

knute...
 
A

Andrew Thompson

Knute Johnson wrote:
....
The easiest solution is to not use a layout manager.

I was just *waiting* for someone to say that. ;-)
...I know that that
sends shudders through the cognoscenti but there are millions of C
programs out there that position their components that way.

I can see how that can work in two situations..
1) If the text size, look and feel and other UI
related matters can be pinned down to the last detail.
That may be true of your typical C program, but Java
GUI's are more *often* X-plat, Multi-PLAF, used under
(potentially) different Java versions and end user
settings (screen res., font size - etc.), any of which
can destroy the rendering of (textual) components in
an 'absolutely positioned' GUI.
...if you are writing a 'run once' dev. tool, I see no
reason to worry about any the above - for most
other Java GUI projects, they become a factor.

2) If the entire content area is something you are about
to render, pixel by pixel (e.g. rotatable 3D wire-frames
or models), but that situation is not one where there is
any point to actually setting a null layout - just override
paint()/paintComponent() and go wild!

...and I ultimately think that if the project actually needs
a PutItWhereverIDropItLayout, it only takes a few lines
of code to turn (whatever) short logic that may entail,
into a LayoutManager.

(I refuse to shudder)

Andrew T.
 
D

Deniz Dogan

A. Bolmarcich said:
GridBagLayout does not support allocating percentages of the container
size among the components in the container. You can get that effect
using GridBagLayout by also overriding the preferred and minimum sizes
of the components. However, it would be better to use a layout manager
that supports the type of layout that you want, such as TableLayout (see
http://java.sun.com/products/jfc/tsc/articles/tablelayout/index.html).

Wow, thanks! That was _exactly_ what I was looking for! You make me so
happy. :)

/Deniz Dogan
 
T

Thomas Weidenfeller

Knute said:
The easiest solution is to not use a layout manager. I know that that
sends shudders through the cognoscenti but there are millions of C
programs out there that position their components that way.

Sure. Only that they are compiled for a particular platform. And tend to
fail in interesting ways when e.g. localized, or the basic geometry of
the platform's widget set changes.

It is also rather frustrating when you once again have to deal with a
list in a window, and can't get all interesting data on the screen at
once, because the C programmer though it was a good idea to use an
non-resizable window. Particular "nice" are also tables where you often
can only get two out of three columns displayed, and need to either
scroll horizontally or shrink a table column to zero width to see the rest.

Non-resizable windows are very often a sign of a lazy or incompetent
programmer.

/Thomas
 
A

A. Bolmarcich

A. Bolmarcich wrote: [snip]
If setSize(400,300) is replaced with pack(), then the width of each
button is 59. Which is a 50%/50% distribution of the width, not
70%/30%.

If the ratios of the preferred and minimum widths of the two buttons
is 70%/30%, then having GridBagLayout distribute 70% of the extra
space to the larger button and 30% of the extra space to the smaller
button will keep the widths of the components in the 70%/30% ratio.

If the components are at their minimum sizes they will probably be the
same size.
[snip]

Because pack() was invoked, the components are at their preferred sizes,
not their minimum sizes. Using your approach, the components are the
same size, but the original poster wanted a 70%/30% distribution.
 
K

Knute Johnson

Knute said:
The easiest solution is to not use a layout manager. I know that that
sends shudders through the cognoscenti but there are millions of C
programs out there that position their components that way.

knute...

Honest, I wasn't really suggesting that he actually do that.

Anyway he likes the TableLayout.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top