Saturday, January 20, 2007

Java6: GroupLayout and a small gotcha


The new layout manager, GroupLayout, which is part of the JavaSE 6 bundle is great and coupled with Netbeans' Matisse component, makes a killer combination. Today I would like to talk about an issue that I ran into and hopefully would be able to help others running into the same issue.

Anyways, if you try hand-coding this layout for your components, there is a rather subtle thing to remember. In Java 5, if you wanted to add a component to a container like JPanel, you would do something like:

....
JPanel jp = new JPanel();
JButton button = new JButton(...);
jp.getContentPane().add(button);
....


The key point to notice is that you would explicitly get hold of the content pane and then add the component to it. Now with Java 6, the good old ways of adding a component directly to the parent are back (which internally ensures that the component is added to the content pane), i.e., the same example above could be simplified as:

jp.add(button);

All this fine and nice. Now when using GroupLayout, the code might look as follows (in Java 5):

GroupLayout layout = new GroupLayout(jp.getContentPane());
jp.getContentPane().setLayout(layout);
... // add the component to the layout

Since I was working with Java 6, I decided to use the simplified notation and did the following:

GroupLayout layout = new GroupLayout(jp);
jp..setLayout(layout);
... // add the component to the layout

And was I in for a shock when I ran the code !!! I kept seeing the following stack trace on my screen :-O

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException:
GroupLayout can only be used with one Container at a time
at javax.swing.GroupLayout.checkParent(GroupLayout.java:1095)
at javax.swing.GroupLayout.invalidateLayout(GroupLayout.java:987)
......

It took me a while (which involved going through the source-code of GroupLayout) to figure out that the problem was actually with the way I am initializing the damn GroupLayout instance! The layout instance considers that it is being applied to the container ( JPanel in our case) whereas, the setLayout() method delegates the call to the content pane. And GroupLayout does a check to see that the host and owner are the same, if not, it throws a rather undecipherable exception like the one above. The key to getting it run was just simply to pass the content pane to the constructor of the GroupLayout instance.

GroupLayout layout = new GroupLayout(jp.getContentPane());
jp..setLayout(layout);
... // add the component to the layout

This experiment sure was good learning, but it would have been great if the implementation of GroupLayout threw a more meaningful exception stating the obvious rather than leaving us to figure out the obscure bits!

Thats all for now.

15 comments:

indiancomet said...

Nice post. This definitely saved me a few hours of labour.

Unknown said...

Glad I was able to help you out

Richard L Wellman said...

Sorry for not taking the time to run your code myself, but... are you sure this problem is with JPanel? I am aware of the problem with JFrames, but have used add with JPanel for a long time now.

OVJ said...

Hi nice post yaar.....I also faced the same problem...Thank you..

Ketan said...

Thanks. That helped me.

David Underhill said...

Thanks, this was quite helpful. This simple error would have definitely wasted a lot of my time if you hadn't solved the problem and blogged about it!

David Underhill

Aaron said...

Thanks ... probably saved me a couple hours of digging!

SHeRrY said...

Thank you so much!! This solved my problem which drove me crazy!!

Unknown said...

That seriously just made my day! Thank you!

Yan said...

Thanks, it helped!

Anonymous said...

made.
my.
day.
!! thx ;)

Ahmed Gaber said...

Nice Post you saved my A** :D

Unknown said...

Glad I could help you guys :)

Jeff said...

"GroupLayout can only be used with one Container at a time"

I've been wrestling with what this meant for the past couple of days. Still trying to learn Java, can't thank you enough for including an explanation of the error that you encountered and how it was resolved in your post. Easy to understand what was happening and it finally makes sense.

Unknown said...

Glad I could help you out Jeff. Just read through the article again and realized that I wrote this one in a hurry :) .. Could use some more clarity.