![]() |
GridBagLayout and its pitfals
This is a repost of the original post with
Subject: Nested GridBagLayout and its pitfals. I decided that the subject would be easier to find if the first word was GridBagLayout. Secondly, I'd like to fix some obvious errors in the original post and I hope that the followups, if any, would be on this thread. - - - - - - - - - - - - - - - - - - - - - - Original post: I am working on one app that has few frames to get/set various program parameters. Some of those frames have several buttons, several text fields with labels, several checkboxes, a text area and, status field and a choice boxes. To make it all look nice and clear from the standpoint of GUI element layout, you would have to get into some pretty hairy issues. Working with it, what I was seeing is nothing less than magic. Buttons would dissapear in run time, text fields would have Y size several times smaller than the font Y size and on and on an on. I could not believe my eyes seeing all that madness, and I ended up spending probably 10 times more time on it all, than it should have taken me, or any mortal for that matter. I decided to use my gadget and review the 25000 article archive of this group, going back at least half a year, and see if this issue was ever discussed. The result was nothing but shock. There were but a handful of articles, most in Sept. 2006, addressing this issue, and even there, the advices were so scetchy, that they were virtually useless, in case of just about any realistic frame imaginable having more than a few similar GUI elements. So, let us attempt to fix that problem and put an end to the whole GridBagLayout debate. I was recomended by one of people here to read the Sun's tutorial on GridBagLayout. Yes, I agree, it is humanly readable, but, unfortunately, the example it provides is nothing more than a childish invention, and there is very little chance it is going to be of any use in any realistic sutuation. It does not address ANY of subtleties of realistic layouts, having not just a bunch of buttons, filling the entire frame, but a mix of various GUI elements. Finally, what i came up with, was a realization that about the easiest and the best way of doing it, was to use nested layouts. Here is summary of what I have found. It is all out of memory as I do not want to load another piece of bloatware and wait for days when I want to switch some tab. So, some things may be named incorrectly, but that is not significant as the very underlying meaning should be clear. 1. In just about any realistic GUI frame, you are likely to have a mix of various elements. If you try to lay them all out using a single GridBagLayout, you'll waste half of your life, being blown out of the chair when you change any parameters. You may try to cheat and create more grid cells, trying to properly position various unrelated groups of elements, trying to make one GUI element to occupy more than one cell in X/Y dimension, trying to accomodate for your positioning requirements, but it will likely to und up in nothing less than utter frustration. So, use nested layout instead. Meaning: Organize all of your similar GUI elements into logically related areas on your frame. Group buttons in one group, labels and text fields in another group, and so the checkboxes, text areas and the rest of it. 2. Create separate panels for each group of related GUI elements Use GridBagLayout for each of those panels. For the group of checkboxes, GridBagLayout is not the best choice as it does not guarantee the equal X offsets between the checkboxes. So, for check box panel, use GridLayout instead as it guarantees the equal X size distribution between all the checkboxes. Use GridBagLayout for the frame itself, and put all those panels into separate cells of the frame's GridBagLayout. 3. Avoid using fills and weights as much as possible as their effect may be such that you'll never have a handle on your layout. Say, for example, you have a group of labels, in Y dimension, that label the corresponding text fields. The entire row of labels will be dimensioned at run time to have an X size of the label having the longest text string. (In fact, in each row, you don't have to worry about the size of each column. At run time, the largest size will be used for the entire column). If you use fills to pad the label column size, and, later on, decide to change the text of your longest label and make it much smaller, all of a sudden, your whole layout will change. Fills are not the absolute size of some GUI element. They are what needs to be added to the size of a text string, that element contains, be it label, button, text field. That is why their are called paddings, which should immediately turn the warning lights on. That means that if you use fills hoping to maximize the size of some row or a column, you'll be sweating half of your life to make it all work, especially if you try to resize that frame in run time. Use insets instead. Those are guaranteed not to change regardless of the size of your GUI element. The easiest thing to think of them is margins. They are expressed in absolute terms - pixels. 4. Minimize the number of constraint parameters used Try to keep all the values of constraints structures at zero instead of filling them with values you THINK will make it look better. Use only those parameters that you feel are absolutely necessary, such as insets. The exception is the row/column numbers and a number of cells you want your GUI element to occupy in X or Y dimension. 5. Paddings of labels, text fields and text related elements On all labels, use a small X padding of 3 - 6 pixels for the labels so that the text field, following that label in X position have some margin and does not run into the end of the label string. Do not use fills or weights on labels, because you will probably want them to stay of exactly the same size and remain the same margins in between when you resize the frame unless they label some elements that will change their position with resizing. 6. Using fills and paddings Try not to use paddings for any of constraints structures for each of your GUI elements, hoping to increase the column width, unless it is absolutely necessary in such cases as when you want to guarantee the minimum length of a text field in X dimension. Paddings are only used to guarantee you extra space in your text fields, text areas, labels, buttons, etc. They should not be used in hope to adjust the column widths as, during the render time, the effects may be utterly different than those you thought you achieved during design time. Secondly, if you change the text of your label or your text field, the effect of padding may end up being something utterly different than what you were hoping to achive. For example, using paddings on your text fields in Y dimension, will increase the Y margin between the different label/text fields in a group, but when you consider weights, the run time behavior may be simply unpredictable. You would probably want your fields and labels to stay equally positioned regardless of the size of your frame and to be guaranteed their minimum size as limited by the font you are using and the length of your string. 7. Testing frame during run time Try to make your frame resizable and resize it in run time. If all the GUI elements and groups keep sane proportions, it means you've got all your constraints and structure of your nested layout correctly configured. 8. Using off the shelf GUI designer If you use a GUI designer, and it generates Java code for your constraints, panels, etc., do not modify that code by hand. You'll waste half of your life if you ever need to change your layout in the future, which is pretty much inevitable. All your hand coded stuff will be either overwritten, or might cause unpredictable behavior of your new version. The same exact code as generated by the GUI designer should work like a champ in just about ANY situation imaginable. Forget about the minimum and preferred sizes. They are virtually useless. You can put some reasonable values in them, but when you try to resize your frame, and hope they mean something, you may be suprised that the minimum and preferred sizes are simply ignored, as far as having anything to do with the look and feel of your frame. I just set them to some reasonable values and forget about them. Even if they are set to 0, and frame is correctly designed, you won't have problems with it in run time. 9. Simplicity of proper structuring If you do your design correctly, you'll have the absolute minimum of various parameters to be set as far as boundaries, sizes, etc., behaving in the most predictable way possible under the Sun. 10. Separation of GUI and the even handling code Separate your GUI related code for the frame and do not add anything to that class beyond get/set methods for each element. Make a superclass that extends that frame and that is where you can add the keyboard and mouse listeners, and all the bells and whistes to your frame. That superclass has access to its underlying frame's variables and has the right to do anything it pleases with those variable, even though it should not attempt to modify the sizes, constraints etc. It all has to be done by the code generated by your GUI designer. 11. Proprietary layout managers Try not to use some proprietary layout managers because they are not guaranteed to work with the future versions, unless they rely on the existing basic layouts, which you can do yourself. Futhermore, they'll end up doing the same thing the GridBagLayout or other basic layouts do, and, if you are trying to be lazy, hoping to save some time or effort, you are likely to regret it at the end, it is all just a matter of time. Also, think about the platform compatibility. Are you sure you will be able to compile your code under different compiler or even a different version of the same compiler? Will it work with different version of jre? Some claim that by using some proprietary layouts, they can save half the amount of code lines, which is about the funniest argument possible. Your frame look and feel is about one of the most important aspects of your entire application. Just about ALL the users will see with your app is those very frames. Trying to save a few hundred bytes or code lines is simply foolish. Instead, let your gui designer generate as many constraints in wants. It does not matter at this state of affairs. A few hundred bytes extra won't change anything even worth mentioning, compared to overall look and feel benefits. But trying to hand tweak the automatically generated code could cost you a bundle at the end. 12. Spend enough time on making sure your frame behaves in a very predictable way regardless of its size. All the GUI elemenents have to look consistent and corresponding margins and offsets should not change when frame is resized, unless you want them to and use weights to tell the proportional relationships. If your elements keep consistent behavior while resizing frame, it implies that all your constraints and the entire logical structure of your frame are correct. 13. Try not to use weights, if at all possible. If your frame has several groups of GUI elements, each having several elements, then what you think is space distribution may end up being utterly different in run time and you'll waste hours if not days, trying to play with those weights. Even if you use weights with such elements as buttons, you may be unpleasantly suprised at how it looks during the render time, especially when you resize your frame. Weights refer to relative distribution of space, within the group of gui elements, they call "display area" - ugggghhhh, and not the frame as such. They do have meaning on a main frame's GridBagLayout, where you can adjust the proportional relationships between different groups. So, if you only have one group of elements in your frame, weights may work fine, but, as in any realistically complex frame, where you have more than one row/column of your main GridBagLayout, the things may and WILL become simply bizzare. You'll sooner go nuts than get the results you expect from all that mess. By changing any element in a different group of elements, the whole frame may look utterly ugly. Even to use weights for each cell of the main gridbag of your frame, hoping that relationship between groups will remain consistent, you may be very unpleasantly surprised with the results while resizing that frame or adding/removing some elements. Weights is probably close to useless if you consider all the remifications of using them in relatively complex frames. But yes, they do work. Only the consequences of them are much harder to predict than it may look at first glance. Summary: Instead of using a single GridBagLayout on just about any realistically complex frame, that has several different types of GUI elements, group the related elements and put them into separate panels. Select the layout for each panel that suits your frame design concepts in the easiest and most natural way. Do not try to make things more complex than necessary hoping to make it look better, as about ALL you are going to get at the end is a royal grade pain on the neck. It won't work. Trust me. Try to use GridBagLayout for all those panels whenever possible as this is the most general purpose layout having all the power to do just about anyting imaginable. But it has its limitations and unpredictability of behavior if you expect some rows or columns to be of equal size regarless of the label, text field or button text string sizes. GridBagLayout is not a good choice for that because the column size relationships may change in run time when user tries to resize the frame, and your columns will end up of not equal size, and, trying to make them of equal size, by using paddings or weights, could end up being a pain on the neck and of a grand proportions. Use as few parameters in your constraints structure as possible. By using nested gridbags, your design will end up being the simpliest possible with WAY more predictable results, the most powerful and flexible, have the smallest amount of various cells possible, and with the smallest amount of various constraint parameters, which will eventually translate into the most stable, predictable and flexible run time behavior that assures minimal amount of maintenance efforts of your code and provide for ease of future modifications. If you follow these few simple advises, you'll be amazed at how much power and flexibility you can achieve with nested GridBagLayout. Good luck. Finally, if any experts around have any comments, it would probably be a good idea to clarify some more subtle points and issues, or correct some errors or philosophical fine points as this information will become a permanent reference on this issue and will be available through argives for generations to come. Simmply sending people to read some Sun "tutorial", you are effectively sending them to hell, as those "tutorials" cover only the most primitive and most basic concepts having virtually nothing to do with a realistic application. Instead, you can spend half an hour of your time and spill out the fine points of this most important thing there is in the entire concept of GUI design, GridLayout, which all would have to learn eventually no matter what. |
Re: GridBagLayout and its pitfals
On Feb 9, 5:09 am, nukl...@invalid.addr (nukleus) wrote:
> to use nested layouts It'a classic common sense in GUI programming in general, not confined to Java. Some of your listed comments I don't agree upon but that is not important for me and probably for others. |
Re: GridBagLayout and its pitfals
In article <1170977421.076330.57040@k78g2000cwa.googlegroups. com>, "hiwa"
<HGA03630@nifty.ne.jp> wrote: >On Feb 9, 5:09 am, nukl...@invalid.addr (nukleus) wrote: > >> to use nested layouts >It'a classic common sense in GUI programming in >general, not confined to Java. > >Some of your listed comments I don't agree upon but >that is not important for me and probably for others. Well, you could take time and comment on specific issues. |
| All times are GMT. The time now is 09:01 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.