2

I am dinamically generating a layout which requires to use relative sizes, the only way I found to do it without using an external Java layout library is GridBagLayout's weightx and weighty.

At this point it has been working exactly as I need with one small exception. When I have one column containing two JPanels with a space distribution of 66.6% and 33.3% respectively and then another column with 3 JPanels using 33.3% of the space each one of them, the 33.3% of the first column is not the same as the 33.3% of the second. I need them to be perfectly aligned.

Unfortunately this is my first post and I am not able to post any pictures, I hope I won't get in trouble for doing the following:

i.stack.imgur.com/avsuA.png

I think I know what the problem is, inside of each JPanel I have one JLabel and since weightx and weighty's definition is "Weights are used to determine how to distribute space among columns (weightx) and among rows (weighty)" I guess the difference between the two 33.3%s is the fact that the second column contains one extra JLabel.

In this thread StanislavL says that the "container asks children for their preferred size", so, I am wondering if the solution is to override JLabel's getPreferredSize method. I am not sure how "dirty" would be to do that, I would appreciate a lot your suggestions to solve this problem.

Thanks in advance!

Diego

Community
  • 1
  • 1
DiegoSahagun
  • 730
  • 1
  • 11
  • 22
  • Would you be willing to place the contents of both panels into a single panel? That would allow you to line everything up perfectly with a single layout. – Mad Physicist Dec 20 '13 at 20:46
  • Thanks for our suggestion, if I understood it correctly, then unfortunately I don't think that is the solution to my problem since I would have a grid which aligns perfectly for this case but I would not be able to specify for example 60%+40% for the left column and 66.6% + 33.3% in the right one. – DiegoSahagun Dec 21 '13 at 17:49
  • Sure you would. That's exactly how GridBagLayout works. I will append an answer with an example shortly. – Mad Physicist Dec 21 '13 at 19:58
  • I am sorry, I see what you mean and you're right, merging the two pink GridBagLayouts into a single one (60+40/66.6+33.3) is completely possible. I see two things, 1) the alignment would probably stay uneven, and 2) since I am generating this layout in a dynamic way based on an XML file, it makes more sense to me to have 2 layouts due to the structure of the XML data. (This is a very basic example but the layout could grow into something more complex). If you still would like to provide a simpler solution I am happy to see it, thank you a lot for the kind support and interest. – DiegoSahagun Dec 22 '13 at 00:22

3 Answers3

1

I am wondering if the solution is to override JLabel's getPreferredSize method.

try it, except I would override the panels getPreferredSize() method, since it the the panels size that will adjust as the frame grows/shrinks.

I am not sure how "dirty" would be to do that

overriding is preferred to using the setPreferredSize() method.

the only way I found to do it without using an external Java layout library

Why not use an external library if it make the code easier to use and understand? Relative Layout was specifically designed for this purpose so you don't have to play around with sizes.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • I overrode the panel's getPreferredSize() method to return a dimension with a height of 0 and it works!So, if you suggest this as a safe way to distribute relatively not only the extra space but all the space of the different cells, then I am pretty happy with the solution. By the way, I suggested MiG Layout to my boss but he doensn't want to integrate libraries, well GridBagLayout is handling it after all. Thanks! – DiegoSahagun Dec 21 '13 at 18:57
  • I am a newbie here and I am confused, what should I do when two people gave effective solutions but each of them contradict the other? using setPreferredSize() vs overriding getPreferredSize(). Thanks for the help, I look forward to be active in the community, I really don't know why I didn't sign up before. – DiegoSahagun Dec 21 '13 at 19:10
  • `what should I do when two people gave effective solutions but each of them contradict the other?` Given that neither answer gives reasons for using one approach over the other it is hard to make an informed decision :) I would tend to look at reputation points. Most long term users of the forum will make suggestions that are the consensus answer of the users in the forum. In this case it becomes more obvious with the solution. You only want to hardcode the height and not the width. This can only be done with the override, because you don't want to hardcode the width. – camickr Dec 21 '13 at 20:21
  • `So, if you suggest this as a safe way to distribute relatively not only the extra space but all the space of the different cells, then I am pretty happy with the solution.` - I always worry a little if you ever need to add the panel to a JScrollPane, because scrolling only works when components have a valid preferred size. So components really should have a valid preferred size but they should be allowed to grow/shrink if necessary. – camickr Dec 21 '13 at 20:27
0

The accepted answer to this question states:

If the space within a Panel is greater than the preferredDimension of the components contained within, the weightx and weighty is used to distribute the extra space to the individual components.

weighty won't "lock" each box to exactly 33% of the height; it doesn't distribute all of the space, but only the extra space.

So, if you need them to line up perfectly, use setPreferredSize (rather than of overriding getPreferredSize as you suggested).

Community
  • 1
  • 1
asaini007
  • 858
  • 5
  • 19
  • Thanks, I have just tried by setting a preferred size's height of 0 and it works! Now I am confused, your answer of course helped me but I don't know who is right about using setPreferredSize() vs overriding getPreferredSize(). – DiegoSahagun Dec 21 '13 at 19:08
0

Use a single GridBagLayout for both columns rather than splitting apart. GridBagLayout allows you to do more than just an HTML table would, without having to hack your size and preferred size methods. You can do something as follows in your frame initializer:

getContentPane().setLayout(new GridBagLayout());
GridBagConstraints constraints = null;
Insets insets = new Insets(0, 0, 0, 0);
...
// upper left hand corner, 1 column wide, 2 rows high, make the column take up half of the total width, the row(s) take up 0.66 of the total height
constraints = new GridBagConstraints(0, 0, 1, 2, 0.5, 0.66, GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0);
getContentPane().add(upperLeftPanel, constraints);

// lower left hand corner, 1 column wide, 1 row high, make the column take up half of the total width, the row take up 0.33 of the total height
constraints = new GridBagConstraints(0, 1, 1, 1, 0.5, 0.33, GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0);
getContentPane().add(lowerLeftPanel, constraints);

// upper right hand corner, 1 column wide, 1 row high, make the column take up half of the total width, the row take up 0.33 of the total height
constraints = new GridBagConstraints(1, 0, 1, 1, 0.5, 0.33, GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0);
getContentPane().add(upperRightPanel, constraints);

// center right hand side, 1 column wide, 1 row high, make the column take up half of the total width, the row take up 0.33 of the total height
constraints = new GridBagConstraints(1, 1, 1, 1, 0.5, 0.33, GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0);
getContentPane().add(centerRightPanel, constraints);

// lower right hand corner, 1 column wide, 1 row high, make the column take up half of the total width, the row take up 0.33 of the total height
constraints = new GridBagConstraints(1, 2, 1, 1, 0.5, 0.33, GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0);
getContentPane().add(bottomRightPanel, constraints);

The various properties of the constraints, as well as the container where you will really add the panels is entirely up to you. You can change the same constraints object or create a new one every time. I have see both used, but tend to favor the latter myself. As you can see, there is no problem adding multiple columns to a single GridBagLayout.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264