N
nukleus
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 wre 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 grdibag 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 to you. 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 layout.
Here is the 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.
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, setting trying to make one
GUI element to occupy more than one cell in X or
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 of those groups,
where you put related items.
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
Y offsets between the checkboxes.
So, for check box panel, use GridLayout instead
as it will guarantee 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
GridBagLayout.
3. Avoid using fills 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.
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 minimize
the size of some row or a column, you'll be sweating
half of your life to make it 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.
4. Try to keep all the values of constraints structure
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. 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.
6. Try not to use fills for any of constraints structures
for each of your GUI elements, unless it is absolutely
necessary in such cases as the length of text field
in X dimension to make sure your field occupies as
much of X dimension of your frame, as possible.
Fills are only applicable to the cases where you resize
frame to make it BIGGER than what you designed with you
GUI designer, or you set the initial size of your frame
bigger than what you saw with your GUI designer.
For example, using fills on your text fields in Y dimension,
will increase the Y margin betwee the different label/text
fields in a group, which is not what you would want to do
in most cases. You would probably want them 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 lengths of your string.
7. Try to make your frame resizable and resize it in
run time. If all the GUI elements and groups keep sain
proportions, it means you've got all your constrains
and structure of your nested layout correctly configured.
8. 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.
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. If you do your
design correctly, you'll have the absolute
minimum of variour parameters to be set
as far as boundaries, sizes, etc.,
behaving the in the most predictable way
possible under the Sun.
9. 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 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.
10. 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 gridbag does, and, if you are trying to be lazy,
hoping to save some time or effort, you are likely
to regret at the end, it is all just a matter of time.
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.
11. 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 should not
change when frame is resized.
If that is the case, it implies that all your
constraints and the entire logical structure
of your frame are correct.
12. 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.
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 gridbag, 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, as those weights only affect
the elements in a group.
Even to use weights for each cell of the maing
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 a relatively
complex frames.
Summary:
Instead of using a single GridLayout 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 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 GridLayout 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.
GridLayout is not a good choice for that because the
column size relationships may change in run time 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, having 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 and having the minimum amount of
maintenance efforts of your code.
If you follow these few simple advises,
you'll be amazed at how much power and flexibility
you can achieve with nested GridLayout.
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.
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 wre 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 grdibag 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 to you. 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 layout.
Here is the 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.
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, setting trying to make one
GUI element to occupy more than one cell in X or
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 of those groups,
where you put related items.
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
Y offsets between the checkboxes.
So, for check box panel, use GridLayout instead
as it will guarantee 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
GridBagLayout.
3. Avoid using fills 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.
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 minimize
the size of some row or a column, you'll be sweating
half of your life to make it 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.
4. Try to keep all the values of constraints structure
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. 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.
6. Try not to use fills for any of constraints structures
for each of your GUI elements, unless it is absolutely
necessary in such cases as the length of text field
in X dimension to make sure your field occupies as
much of X dimension of your frame, as possible.
Fills are only applicable to the cases where you resize
frame to make it BIGGER than what you designed with you
GUI designer, or you set the initial size of your frame
bigger than what you saw with your GUI designer.
For example, using fills on your text fields in Y dimension,
will increase the Y margin betwee the different label/text
fields in a group, which is not what you would want to do
in most cases. You would probably want them 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 lengths of your string.
7. Try to make your frame resizable and resize it in
run time. If all the GUI elements and groups keep sain
proportions, it means you've got all your constrains
and structure of your nested layout correctly configured.
8. 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.
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. If you do your
design correctly, you'll have the absolute
minimum of variour parameters to be set
as far as boundaries, sizes, etc.,
behaving the in the most predictable way
possible under the Sun.
9. 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 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.
10. 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 gridbag does, and, if you are trying to be lazy,
hoping to save some time or effort, you are likely
to regret at the end, it is all just a matter of time.
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.
11. 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 should not
change when frame is resized.
If that is the case, it implies that all your
constraints and the entire logical structure
of your frame are correct.
12. 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.
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 gridbag, 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, as those weights only affect
the elements in a group.
Even to use weights for each cell of the maing
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 a relatively
complex frames.
Summary:
Instead of using a single GridLayout 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 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 GridLayout 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.
GridLayout is not a good choice for that because the
column size relationships may change in run time 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, having 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 and having the minimum amount of
maintenance efforts of your code.
If you follow these few simple advises,
you'll be amazed at how much power and flexibility
you can achieve with nested GridLayout.
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.