File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Swing / AWT / SWT and the fly likes GridBagLayout Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "GridBagLayout" Watch "GridBagLayout" New topic
Author

GridBagLayout

Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
Clearly my concept of Swing/GridBagLayout is not accurate, I'm not sure exactly what assumption(s) I'm making that are leading me astray or what it is I'm trying to do that's causing me issues. Anyway, here's a snippet of my use of GridBagLayout and I'd like it if some of you could list whatever you see me doing wrong or what you see wrong with my approach. There's at least one very obvious problem with the patientStateLabel being placed in the same spot as the patientCityLabel and I'm not even sure what's causing that. Thanks!

[ December 25, 2003: Message edited by: Ken Blair ]
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Hi Ken,
By doing this modification it goes ok.
add(layout, c, patientStateLabel, 26, 7, 4, 1);
I feel strange that all the components overlap each other. A component placed at gridx=1 and streching over 30 cells (gridwidth=30) gets overlapped by the leftmost part of other component placed at gridx=30.
Try avoiding the overlapping for all the components and tell me if it works.


SCJP2. Please Indent your code using UBB Code
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
Okay I didn't realize I had a cell overlapping. Anyway, I add the JTextFields for the city & state and the two end up equal size even though one spans 25 cells and the other only spans 5, every item has the exact same weight though. Okay, I could understand that if the preferred/minimum sizes were such that it needed that much room to fit and the other had an excess, but they're always the same size even when you expand the window. Why doesn't the city get bigger than the state?
[ December 22, 2003: Message edited by: Ken Blair ]
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Columns or rows that consist only of empty cells do not count when calculating the real columns or rows. I think this is so because they have no dimension at all.
In the following example the two buttons occupy almost the same space, even though the first is given gridwidth=10 . If you run the code commented out, the first button receives the width of the ten cells because they hold a component, and thefore, have a size.

As a general guideline for using a GridBagLayout, draw a grid in a a piece of paper and then lay your design on it.
Doing that, there is no sense in assigning a component 60 empty cells; empty rows or columns will not be taken into account by GridBagLayout.
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
What do you mean "empty"? One spans thirty, one below it spans 25 and another 5, below that one spans 18 and another 12, etc. I did make a grid and in order to get all the components in and at appropriate sizes relative to each other I needed about 90 cells.
[------30-----]
[---25---][-5-]
[-12-][---18--]
[-16---][--14-]
How else might I lay out the components above? I don't see how I can do that with fewer cells unless I start breaking up the entire thing into half a million panels and that's exactly what I'm trying to avoid. I understand what you're saying, I want to know how to 'fix' that or get around it.
[ December 24, 2003: Message edited by: Ken Blair ]
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
In my example when only two buttons are added I think there is a unique column formed. Thus you can think that the others do not exist. Or that they exist but they are empty. My guess goes more with the former. Anyway, in an informal way -just to agree on what we are talking about- I am calling an empty cell to those that do not hold a component, or that hold only a part of it. I think that a cell that does not hold a component completly within its bounds has no size, and it is not shown.
The following code represents, with buttons, the firts and last rows of your example. I did not draw on a paper but I figured out looking at the output of the program:
I looked at all the rows to know the number of columns we need. "City", "St.", "Birthdate", "Sex", "City" and "St." make 6 columns.
Based on that "Program type" is (gridx=0 , gridwidth=4) ; and "Insured Id" is (gridx=4 , gridwidth=2)
Also notice that "Patient Status" receives (gridwidth=2) because "Birthdate" and "Sex" will occupy the same room when added.

For the relative size of the components I have used ipadx that gets added to both sides of a component. I think it increases the preferred size of the component. You can also use setPreferredSize directly.
In order to add space between components you can use insets or set an empty border around them.

The way to go with GridBagLayout is to proceed in a similar fashion with a drawing on a piece of paper.
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078

In this case the third column contains the top right textfield and should take up one third of the width. The bottom two textfields should each take up half the width. In order to do this I logically need a minimum of three columns, one at a third the width, one at half the width, and one to take up the difference between the two. FieldA takes up columsn 0 and 1, B takes up column 2, C takes up column 0, and D takes up column 1 and 2. That is entirely logical and my understanding of how you'd use GridBagLayout. However, in this instance GridBagLayout doesn't do that at all. No, instead of making use of the middle column it only uses the right column, making it somewhere between the half the bottom field needs and the third the top field needs so that NEITHER field is what it should be. WHY THE HELL DOES IT DO THAT? *cries* How do I make it stop!
EDIT: Okay if I go in and set the individual column weights via the layout.columnWeights it works. Is there anyway around having to set each and EVERY column weight?
[ December 25, 2003: Message edited by: Ken Blair ]
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
I hope this is what you are striving for:

Three columns, total width is 180.
First column has the width of fieldC 2/3 = 90
Second has the width of an empty label 2/3 - 1/2 = 30
Third has the width of labelA 1/3 = 60

[ ][labelA] 2/3-1/2, 1/3
[ fieldA ][fieldB] 2/3, 1/3
[ fieldC ][ fieldD ] 1/2, 1/2

I do not feel that GridBagLayout is a good choice for this design. The main problem is that columns are not well defined.
An easy way to do it with GridBagLayout is placing fieldC and D within a panel managed by GridLayout and giving it gridwith=3 .
I will try to explain it using a single panel managed by GridBagLayout.

The empty "label" is placed in the second column, because otherwise an empty column will not be taken into account by GridBagLayout. It receives weightx=0.2 that represents 2/3 - 1/2 being the total width 1.0
Because all the cells in a column must have the same width, the weigthx of a column is the maximum weigthx of the cells it contains.
The problem is how the weightx of components that strech over several rows affect to those of components in a single row. I think the latter prevail when computing the maximum weightx of a column. In fact if you set weightx of fieldC to 0.0 , this component(its column) will not receive any extra space when resizing; even though fieldA weightx is 0.7
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
oops the quote ruined my lovely drawing.


In my previous post were it says
First column has the width of fieldC 2/3 = 90
It should say
First column has the width of fieldC 1/2 = 90
[ December 25, 2003: Message edited by: Jose Botella ]
[ December 27, 2003: Message edited by: Jose Botella ]
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
I see what you're saying and you're right it's a problem with how it uses components stretching over multiple columns. What I would expect is for it to determine that the first column has a minimum weight of 0.5, the second has a minimum of 0.0, and the third has a minimum of 0.3. Given that situation I would expect it to give the left over 0.2 to the middle column to balance it out. That way the left gets the half it needs, the right gets the third it needs, and the middle takes up the extra space. Unfortunately it doesn't do this, it gives the middle column no size and the right column an average of what the two components want. That doesn't make any sense, I mean if you calculate the columns and discover that the minimum is 0.3 and this field needs 0.5, the logical conclusion would be that a minimum of 0.2 needs to be assigned to the other columns this component spans. Since it only spans another column, and that column has no conflicting weights, you would logically make that column 0.2. Oh well, a flaw in the algorithm they use?
Anyway, to my understanding GridBagLayout is -perfect- for this situation since the columns and rows -don't- have to be equal sizes. Unfortunately it looks like I'm going to have to go in and define each column weight myself since it's not doing a very good job on its own. A little extra work but it looks like it's doing fine so far, and what other layout would I use? I tried SpringLayout but I've had all kinds of problems getting it to scale the way I want it to. That and how do you get more than one row to stretch horizontally if you can only attach one spring to the edge of the container?
[ December 25, 2003: Message edited by: Ken Blair ]
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
weightx dictates how the extra/negative space is distributed among the columns of the grid, when resising or setSize is used instead of pack. The values are relative. You can have all the columns with 1.0 and they will recieve the same space. Thus the algorithm cannot calculate 0.2 for the second column because it does not assume the total width is 1.0
The point is to make the second column a size of 2/3 - 1/2 for the design to appear as we want. I have used a component that prints nothing for that. If we let that component with weightx 0.0 , the relationship among the columns of the grid will vary when resizing. Setting it to 2/3 - 1/2 of 1.0 keeps the proportions, also, in that case.
My concern about using GridBagLayout without panels for this kind of design is:
a) by adding more rows with "dangling" components we can overcomplicate the design with columns holdings invisible components.
b) by adding more rows, a component may be placed in a column for which its weightx setting is incovenient. Say, a component in the first column below fieldC, whose weightx is 0.7, will make the weightx of the first column 0.7 ; which is incompatible with our necessity of 0.5 for that column.
It can be argued: I will never lay such a component in such a place. I am just wondering myself if more rows as seen above would be manageable without intermediate panels.
Please let me know if you write that program
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
The point is to make the second column a size of 2/3 - 1/2 for the design to appear as we want. I have used a component that prints nothing for that. If we let that component with weightx 0.0 , the relationship among the columns of the grid will vary when resizing. Setting it to 2/3 - 1/2 of 1.0 keeps the proportions, also, in that case.

The point is to make the second column 20% of the space being used, whatever that may be. Since the Label takes up the entire space being used and has a weightx of 1.0, 0.2 should be 20% of that space. 0.5 should be 50% and 0.3 should be 30%. The right column has to be 0.3, it simply must, the only component using that column exclusively is fieldB, and in order for fieldB to meet its weightx of 0.3 the entire column must do so. The same is true of the left column because of fieldC. Given this it shouldn't be too much to expect for GridBagLayout to do the math and understand that since left MUST be 0.5 and right MUST be 0.3 and the top that spans all three expects 1.0 and the bottom right that spans one to be determined and one that is 0.3 that the other should be 0.2. I'm not really surprised it doesn't, I mean if I were coding GridBagLayout I'd have a HELL of a time of coming up with good ways to sort all the weights out. However, one thing I always strive for is giving users and programmers alike as much control over as possible and they allow us to go in and overwrite the column weights so that's just what I'll have to do. Truth be known it's probably less trouble than setting every component's weight anyway.

a) by adding more rows with "dangling" components we can overcomplicate the design with columns holdings invisible components.

The only way to do this type of thing is to add enough columns. What I needed to do was take the medical form I'm replicating and draw a line down it every place I want a component to begin and end. The result is nine lines creating seven columns. I need every single one of these columns to create the correct spacing, and some of these columns need to be what you would call "empty", though I really think that is a misnomer since they do have components that use them.

b) by adding more rows, a component may be placed in a column for which its weightx setting is incovenient. Say, a component in the first column below fieldC, whose weightx is 0.7, will make the weightx of the first column 0.7 ; which is incompatible with our necessity of 0.5 for that column.

You're right, I won't add anything like that under it. This GUI form will probably never again be touched, it won't need to be because it's event driven and the program operates on MVC. The only thing I can think of that might get changed in the future would be the listeners, and even that is unlikely unless there's a drastic change in our architecture. In which case the whole thing is probably going to be thrown out and redone anyway.
If you seriously want to see the code for the GUI, or the layout at least, I'll post it in this thread when I finish it up over the next few days.
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120

The point is to make the second column 20% of the space being used, whatever that may be. Since the Label takes up the entire space being used and has a weightx of 1.0, 0.2 should be 20% of that space. 0.5 should be 50% and 0.3 should be 30%. The right column has to be 0.3,

This is so because we have rounded 1/3 to 0.3, then 2/3 - 1/2 becomes 0.2
It would be instructive for me to see a design with many components like fieldA and fieldD without intermediate panels. If you have such a beast it would be nice of you to share it. Thank you.
[ December 27, 2003: Message edited by: Jose Botella ]
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: GridBagLayout