The horror of making layouts in Swing
Tuesday, 9. September 2008, 22:56:25
This week I've been working on a mandatory task in Java Programming. It's quite simple, but I figured I'd make a challenge to it by adding a GUI. I have been working with Java GUI earlier on, but I barely remembered the horrors of how annoying the layout manager can be.
Let's start off with a simple example, and how it usually works.

This is quite simple, it contains a text input box, a button and a label, three quite easy things to stuff into the JPanel.
Fair enough, right? Right. But when you are making more complex solutions, things get a much more nasty.
Now I do not say that I am an expert of Java and its GUI functions, but some of the aspects are quite annoying. Nested layouts are very messy. Let's take another example:

Now, I might not have used the best variables (I probably should have used label_ and button_ or such as prefixes for the different element types), but the thing is that it gets quite complexly in the end with even more nested layouts.
I know that there are different layout types, but I found grid to be the easiest. Though grid has some flaws, for instance: If my main window is 200 pixels in height and I have a GridLayout(2,1) for a JTextField and a JButton, I will get a JTextField of 100 pixels in height and a JButton with 100 pixels in height. I miss the possibility to set custom heights of different rows. There are other layout managers offering this, but I do not feel like I want to write 50 lines of code to be able to get this simple layout. A good example of the above scenario is this:

I will continue study this and hopefully figure out to use Swing's layout managers better. It seems I will be stuck with Java for quite some time.
Let's start off with a simple example, and how it usually works.

This is quite simple, it contains a text input box, a button and a label, three quite easy things to stuff into the JPanel.
// ...
JPanel panel = new JPanel();
JLabel label = new JLabel("");
JTextField text = new JTextField(15);
JButton button = new JButton("Press me!");
panel.setLayout(new GridLayout(3, 1)); // A grid with 3 rows, 1 column.
panel.add(text);
panel.add(button);
panel.add(label);
getContentPane().add(panel);
validate(); // To refresh the frame making changes to it visible
Fair enough, right? Right. But when you are making more complex solutions, things get a much more nasty.
Now I do not say that I am an expert of Java and its GUI functions, but some of the aspects are quite annoying. Nested layouts are very messy. Let's take another example:

JButton button;
JLabel nc, n, a, p;
JTextField numbercode, name, amount, price;
JPanel behind, panel;
behind = new JPanel();
panel = new JPanel();
button = new JButton("Display receipt");
button.addActionListener(new Listener()); // I won't add the code for this class
nc = new JLabel("Number code: ");
n = new JLabel("Name: ");
a = new JLabel("Amount: ");
p = new JLabel("Price: ");
numbercode = new JTextField(10);
name = new JTextField(50);
amount = new JTextField(3);
price = new JTextField(7);
behind.setLayout(new GridLayout(2, 1));
panel.setLayout(new GridLayout(4, 2));
panel.setBorder(BorderFactory.createEmptyBorder(30,30,10,30)); // A cute border
// Let the fun begin
panel.add(nc);
panel.add(numbercode);
panel.add(n);
panel.add(name);
panel.add(a);
panel.add(amount);
panel.add(p);
panel.add(price);
behind.add(panel);
behind.add(knapp);
getContentPane().add(behind);
validate();
Now, I might not have used the best variables (I probably should have used label_ and button_ or such as prefixes for the different element types), but the thing is that it gets quite complexly in the end with even more nested layouts.
I know that there are different layout types, but I found grid to be the easiest. Though grid has some flaws, for instance: If my main window is 200 pixels in height and I have a GridLayout(2,1) for a JTextField and a JButton, I will get a JTextField of 100 pixels in height and a JButton with 100 pixels in height. I miss the possibility to set custom heights of different rows. There are other layout managers offering this, but I do not feel like I want to write 50 lines of code to be able to get this simple layout. A good example of the above scenario is this:

I will continue study this and hopefully figure out to use Swing's layout managers better. It seems I will be stuck with Java for quite some time.




Quinnuendo # 11. September 2008, 20:39
Test BoxLayout too.
What sources are you using for learning? I found "Thinking in Java" is pretty good, and you can get it free in electronic formats on the authors site. Though the part about layout is good, but not too thorough.
The java sun tutorials are also good.
And for a nice and flexible LayoutManager I would recomend to go for GridBagLayout. Yes most say it is comlicated and only for automated generation of code, but I disagree. With a bit of testing and getting to know it, you can put things in rows with dynamic height, make some cells take up two or more rows or columns etc.
I think I read about it in the java tutorial and in it's documentation of course.
If you have problems finding good sources, tell me and I'll try getting some links.
good luck javaing
Amnith # 11. September 2008, 22:44
I did some brief lookthrough of my mandatory works, and I figured that the layout description took about 60-70% of the code lines. Of course, it's quite basic code elsewise, but you hopefully get my point.
Lastly, I'd like to link to my finished projects so that you could see the layout in action if you'd like. It's in Norwegian, but basically you can see the layouts nonetheless.
http://files.ipwn.se/Kvittering.jar
http://files.ipwn.se/Vekslomat.jar
The last ones are quite boring, so I'm only linking the two that has more complex layouts. For my next mandatory work in programming, I will try to write the layouts even more complex (if the task allows for it - I won't write a complex layout for something that asks me to figure whether X is a prime number or not
Thank you for your insightful comment!
Quinnuendo # 12. September 2008, 11:40
I took a look at the jars, they seem fine for start
also border layout can be good when you want to put a button, or a label or something in the bottom (or top) of a panel.
those layouts are pretty basic, and usually as you have found out, you need to put a lot of intermediate containers to handle everything.
but for one, you know that the layout has nothing to do with the behaviours and the actions, and you can always change it independantly.
I have used Swing for some time now, and there are a lot of cool features there. The menus are pretty good, creating abstract actions you can connect to a button, or menu or anything at the same time, and a lot of other things.
as I said those basic layouts are a bit lacking, but the were made to be simple to use.
I think you will find that GridBagLayout has what you need.
Amnith # 12. September 2008, 15:03
I will get a new task next Friday, and I will try GridBagLayout then. Could you perhaps write me a very simple layout in GridBagLayout with, say, a couple of JLabels, JTextFields, JTextAreas and JButtons? :-) It's much easier to adapt when I find a cuddly example. My 3 minutes Googling showed GridBagLayouts which yielded walls of code. I might have used the wrong search phrase though. :X
Thanks for your comment. :-)
Quinnuendo # 12. September 2008, 18:08
http://java.sun.com/docs/books/tutorial/uiswing/layout/gridbag.html
and would recomend checking out the java api fro the gridbaglayout class.
maybe I'll post my program that uses it, but it's in Serbian, and the comments also, could be a problem for you...
Amnith # 12. September 2008, 22:16
Thanks for the link, I'll check it out. :-)
leirom # 4. October 2008, 09:26